我想更好地使用NUnit来测试我编写的应用程序,但我经常发现我编写的单元测试有一个直接链接到开发机器上的环境或底层数据库.
让我举个例子.
我正在编写一个单独负责重写字符串的类,该字符串已由另一个应用程序存储在注册表中.密钥存储在HKCU\Software\CustomApplication\IniPath中.
我最终写的测试看起来像这样;
[Test] public void GetIniDir() { RegistryReader r = new RegistryReader(); Assert.AreEqual(@"C:\Programfiles\CustomApplication\SomeDir", r.IniDir); }
但问题是字符串@"C:\ Programfiles\CustomApplication\SomeDir"现在真的是正确的.明天它可能已经改为@"C:\ Anotherdir\SomeDir",突然间,即使代码没有改变,也会破坏我的单元测试.
当我创建一个对数据库执行CRUD操作的类时,也会出现此问题.数据库中的数据可以随时更改,这反过来会使测试失败.因此,即使我的类完成了预期的操作,它也会失败,因为数据库会返回我最初编写测试时所拥有的更多客户.
[Test] public void GetAllCustomersCount() { DAL d = new DAL(); Assert.AreEqual(249, d.GetCustomerCount()); }
你们有没有关于编写不依赖周围环境的测试的技巧?
这个问题的解决方案众所周知:嘲弄.将代码重构为接口,然后开发假类来实现这些接口或使用模拟框架模拟它们,例如RhinoMocks,easyMock,Moq等.人.使用伪类或模拟类允许您定义接口为测试返回的内容,而无需实际与外部实体(如数据库)进行交互.
有关通过SO进行模拟的详细信息,请尝试以下Google搜索:http://www.google.com/search?q = mock + site:stackoverflow.com.您可能也会对以下定义感兴趣:伪造,嘲弄和存根之间的区别是什么?
此外,良好的开发实践,例如依赖注入(如@Patrik建议),允许将类与其依赖项分离,以及避免静态对象,这使得单元测试更加困难,将有助于您的测试.使用TDD实践 - 首先开发测试 - 将帮助您自然地开发包含这些设计原则的应用程序.