使我的静态类可测试的最佳方法是什么?
在我的 asp.net 应用程序中,我有以下静态类来处理我的应用程序中的某些类具有依赖关系的查询字符串:
public static class QueryStringUtil
{
public static int? GetStoreId()
{
return GetId(QueryStrings.StoreId);
}
public static string GetItemCode()
{
return Get(QueryStrings.ItemCode);
}
private static string Get(string queryStringName)
{
return HttpContext.Current.Request.QueryString[queryStringName];
}
private static int? GetId(string queryStringName)
{
var queryString = Get(queryStringName);
int queryStringParsed;
return int.TryParse(queryString, out queryStringParsed) ? (int?)queryStringParsed : null;
}
}
使此类可测试的最佳方法是什么?
我知道的一种方法是重构它并创建一个单例实例类,而不是它的接口,并使依赖类能够接受我的单例类的接口。不确定这是否是我最好的选择。
另一种选择是使我的类成为带有接口的普通类,然后创建一个单例 ServiceLocator 类,负责保存所有应该表现得像单例的类的实例,例如我的 QueryStringUtil,然后允许我的依赖类接受我的 IQueryStringUtil 的接口。
我能想到的第三个选项是不使用自定义服务定位器类,而是使用 IoC 容器(例如 Microsoft Unity),然后在 IoC 容器配置文件中保存一个单例实例并将其注入到我的依赖类中。
请告知您的最佳选择以及原因。
非常感谢,
In my asp.net application, I have the below static class to handle query strings in my app to which some classes have dependency:
public static class QueryStringUtil
{
public static int? GetStoreId()
{
return GetId(QueryStrings.StoreId);
}
public static string GetItemCode()
{
return Get(QueryStrings.ItemCode);
}
private static string Get(string queryStringName)
{
return HttpContext.Current.Request.QueryString[queryStringName];
}
private static int? GetId(string queryStringName)
{
var queryString = Get(queryStringName);
int queryStringParsed;
return int.TryParse(queryString, out queryStringParsed) ? (int?)queryStringParsed : null;
}
}
What would be the best way to make this class testable?
One way that I know would be to refactor this and create a singleton instance class instead with its interface and enabling the dependent classes to accept an interface of my singleton class. Not sure it would be my best option.
Another option would be to make my class a normal class with interface and then creating a singleton ServiceLocator class responsible to hold instances to all classes that should behave like a singleton, such as my QueryStringUtil, then allowing my dependent class to accept interface to my IQueryStringUtil.
Third option I can think of is not using my Custom Service Locator class instead using an IoC container, such as Microsoft Unity, then holding a singleton instance in the IoC container config file and injecting that to my dependent classes.
Please advise your best option and why.
Many thanks,
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我真的很喜欢 IoC 容器的最后一个选项。这就是它的力量——它负责对象的生命周期和依赖关系。
I really like the last option with the
IoC
container. This is its power - it is responsible for the lifecycle and dependencies of your objects.我更喜欢 IoC 容器中的接口和普通类。您可以使用任何模拟框架创建实例并控制发送到测试类/方法的值。否则,您将被迫使用一些隔离框架(如 TypeMock 或 Moles)来模拟静态方法中的值。
I prefer interface and normal class in IoC container. You can create instances and control values sended to your tested classes/methods with any mocking framework. Otherwise you will be forced use some isolation framework like TypeMock or Moles to simulate values from your static methods.
我知道我偏离了主题,但我认为您并不是在谈论使此类可测试,而是在谈论使依赖于它的其他类可测试。
当您测试这些类时,也许拥有 QueryStringUtil 的接口可能会很有用......?
然而,为了尝试更通用的答案,任何类型的单例都是测试责任(它是全局状态的一种形式,就像全局变量、文件或数据库一样)。
这个问题的一般答案是使用依赖注入(我认为这个名字比“控制反转”更精确和容易理解,这实际上根据不同的人意味着几种不同的东西)。
我对 Asp.net 不熟悉,所以我无法告诉您要使用哪个库,但您可以毫无问题地找到一个。
依赖注入将使用单例,但不在您的代码中,因此您可以测试您的代码,就像它不是单例一样。
I know I'm off the point, but I think you're not talking about making this class testable, but about making other classes that depend on it testable.
When you are testing these classes, maybe having an interface for QueryStringUtil might be useful ... ?
However, to try a more general answer, any type of singleton is a testing liability (it is a form of global state, just like global variable, file or database).
The general answer to this problem is to use Injection of Dependencies (I think that name is more precise and understandable than "Inversion of Control", that actually means several different things according to different people).
I'm not familiar with Asp.net, so I can't tell you which library to use, but you will have no problem finding one.
Dependency injection will make use of a Singleton, but not in your code so you can test your code as if it wasn't a Singleton.