我已经使用Visual Studio Team Edition测试框架准备了一些自动测试.我希望其中一种测试按照程序中正常的方式连接到数据库:
string r_providerName = ConfigurationManager.ConnectionStrings["main_db"].ProviderName;
但是我在这一行收到一个例外.我想发生这种情况是因为ConfigurationManager是单例.您如何通过单元测试解决单例问题?
感谢您的答复.所有这些都非常有启发性。
- 2021-1-101 #
- 2021-1-102 #
您可以使用构造函数依赖注入.示例:
public class SingletonDependedClass { private string _ProviderName; public SingletonDependedClass() : this(ConfigurationManager.ConnectionStrings["main_db"].ProviderName) { } public SingletonDependedClass(string providerName) { _ProviderName = providerName; } }
这使您可以在测试期间将连接字符串直接传递给对象。
此外,如果您使用Visual Studio Team Edition测试框架,则可以将带有参数的构造函数设为私有,并通过访问器测试该类。
实际上,我通过模拟解决了这类问题.示例:
您有一个依赖于单例的Class程:
public class Singleton { public virtual string SomeProperty { get; set; } private static Singleton _Instance; public static Singleton Insatnce { get { if (_Instance == null) { _Instance = new Singleton(); } return _Instance; } } protected Singleton() { } } public class SingletonDependedClass { public void SomeMethod() { ... string str = Singleton.Insatnce.SomeProperty; ... } }
首先
SingletonDependedClass
需要重构以采取Singleton
实例作为构造函数参数:public class SingletonDependedClass { private Singleton _SingletonInstance; public SingletonDependedClass() : this(Singleton.Insatnce) { } private SingletonDependedClass(Singleton singletonInstance) { _SingletonInstance = singletonInstance; } public void SomeMethod() { string str = _SingletonInstance.SomeProperty; } }
威兹维兹测试 (使用Moq模拟库):
SingletonDependedClass
- 2021-1-103 #
[TestMethod()] public void SomeMethodTest() { var singletonMock = new Mock<Singleton>(); singletonMock.Setup(s => s.SomeProperty).Returns("some test data"); var target = new SingletonDependedClass_Accessor(singletonMock.Object); ... }
:有效使用旧版代码这里也给出了相同的答案: https://stackoverflow.com/a/28613595/929902
要在测试工具中运行包含单例的代码,我们必须放宽singleton属性.这是我们的方法.第一步是向单例类添加新的静态方法.该方法允许我们替换单例中的静态实例.我们称它为 Example from Book .
setTestingInstance
现在有了该设置器,我们可以创建一个测试实例 并设置PermitRepository.我们想在测试设置中编写如下代码:
public class PermitRepository { private static PermitRepository instance = null; private PermitRepository() {} public static void setTestingInstance(PermitRepository newInstance) { instance = newInstance; } public static PermitRepository getInstance() { if (instance == null) { instance = new PermitRepository(); } return instance; } public Permit findAssociatedPermit(PermitNotice notice) { ... } ... }
- 2021-1-104 #
您在这里面临一个更普遍的问题.如果滥用,则Singletons会妨碍获得证明.
我已经在分离设计的背景下对此问题进行了详细的分析.我将尝试总结我的观点:
如果您的Singleton具有重要的全局状态,请不要使用Singleton.这包括持久性存储,例如数据库,文件等。
如果类名称对单例对象的依赖性不明显,则应注入依赖性.将Singleton实例注入类的需求证明了该模式的错误用法(请参见第1点).
假设Singleton的生命周期与应用程序的生命周期相同.大多数Singleton实现都使用延迟加载机制实例化自己.这是微不足道的,它们的生命周期不太可能改变,否则您不应该使用Singleton。
public void setUp() { PermitRepository repository = PermitRepository.getInstance(); ... // add permits to the repository here ... PermitRepository.setTestingInstance(repository); }
相关问题
- java:对不同的JUnit测试使用不同的类加载器?javaunittestingjunitsingleton2020-12-21 21:53
看看Google Testing博客:
Using dependency injection to avoid singletons
Singletons are Pathological Liars
Root Cause of Singletons
Where have all the Singletons Gone?
Clean Code Talks - Global State and Singletons
Dependency Injection.
还有:
Once Is Not Enough
Performant Singletons
最后,Misko Hevery在他的博客上写了一篇指南:编写可测试代码。