Answers:
我讨厌看到简单的具体类被嘲笑。例如,使用下面的简单类,该类不依赖于其他任何东西:
public class Person
{
private readonly string _firstName;
private readonly string _surname;
public Person(string firstName, string surname)
{
if (String.IsNullOrEmpty(firstName))
{
throw new ArgumentException("Must have first name");
}
if (String.IsNullOrEmpty(surname))
{
throw new ArgumentException("Must have a surname");
}
_firstName = firstName;
_surname = surname;
}
public string Name
{
get
{
return _firstName + " " + _surname;
}
}
}
在涉及该类的任何测试中,我宁愿实例化并使用一个真实的类,而不是拔出诸如“ IPerson”之类的接口,一个已使用的模拟类并在其上设置期望。通过使用真实的测试,您的测试将更加真实(您已经进行了参数检查,并真正实现了“ Name”属性)。对于像这样的简单类,您不会使测试变慢,确定性降低或使逻辑混乱(您无需在测试其他类时就知道Name被调用)-这是嘲笑/存根。
作为对此的扩展,我还看到人们编写了带有期望值的模拟程序的测试,然后在测试中直接调用该模拟程序。毫无疑问,测试将始终通过...嗯...
听起来似乎很明显,但是:不要在生产代码中使用模拟对象!我已经看到了不止一个示例,其中生产代码取决于某些模拟对象的特性(MockHttpServletRequest
例如,来自Springframework)。
我认为这是对模拟的过多方法调用检查。我觉得这是由EasyMock之类的一些模拟框架强制实施的一种做法,其中默认的模拟行为是每当存在以前未完全指定的其他方法调用时都会失败。这种严格的模拟方法检查可能导致脆弱的设计,即使核心功能仍然相同,对代码进行的最小更改也可能导致整套测试失败。
解决此问题的方法是开始使用存根而不是模拟。我发现特别启发该主题的一篇文章是在Mockito的Javadoc中找到的:http ://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html (请参阅“ 2.存根怎么样?”。 ),链接到:http : //monkeyisland.pl/2008/07/12/should-i-worry-about-the-unexpected/。
到目前为止,我很喜欢与Mockito一起工作,因为它不执行这种严格的模拟行为,而是使用存根。它还对特定对象而不是整个模拟对象强制执行方法检查。因此,您最终只能检查在您的测试方案中真正重要的方法。
这里有几本书,我建议您去摸一下这个主题以及嘲讽和一般:
xUnit模式
单元测试的技巧:.Net中的示例
下一代Java测试:TestNG和高级概念(本书主要是关于testNG的,但是有一章很好地介绍了模拟)
Answer.RETURNS_SMART_NULLS
设置,可帮助诊断此问题。