首先,我不得不说,我是嘲笑的新手。所以也许我错过了一点。
我也刚刚开始习惯TDD方法。
因此,在我的实际项目中,我正在处理业务层中的类,而数据层尚未部署。我想,这是开始嘲笑的好时机。我正在使用Rhino Mocks,但是在编写类本身之前,我遇到了需要知道类的实现细节的问题。
Rhino Mocks检查是否实际调用了预期调用的方法。所以我经常需要知道测试方法首先调用哪个模拟方法,即使它们可以按任何顺序调用。因此我在测试之前经常编写复杂的方法,因为我知道这些方法的调用方式已经过去了。
简单的例子:
public void CreateAandB(bool arg1, bool arg2) {
if(arg1)
daoA.Create();
else throw new exception;
if(arg2)
daoB.Create();
else throw new exception;
}
如果我想测试这个方法的错误处理,我必须知道首先调用哪个方法。但我不希望在编写测试时先了解实现细节。
我错过了什么吗?
答案 0 :(得分:4)
你有2个选择。如果该方法应该导致您的课程发生一些变化,您可以测试您的方法的结果。那么你可以调用CreateAandB(true,false)
然后调用其他方法来查看是否创建了正确的东西。在这种情况下,你的模拟对象可能是只提供一些数据的存根。
如果doaA
和doaB
是注入到您的类中的实际在DB或类似数据中创建数据的对象,您无法验证测试中的结果,那么您需要测试与它们的交互,在这种情况下,您创建模拟并设置期望,然后调用方法并验证是否满足期望。在这种情况下,您的模拟对象将是模拟并将验证预期的行为。
是的,您正在测试实现详细信息,但您正在测试的详细信息,如果您的方法正确使用其依赖项,这是您要测试的内容,而不是如何它正在使用它们,这是你不感兴趣的细节。
修改强>
IDao daoA = MockRepository.GenerateMock<IDao>(); //create mock
daoA.Expect(dao=>dao.Create); //set expectation
...
daoA.VerifyExpectations(); //check that the Create method was called
您可以确保期望按特定顺序发生,但不能使用我认为(source from 2009)可能已更改的AAA语法,编辑see here以获取可能有效的选项),但似乎有人开发了一种可能允许此here的方法。我从来没有用过它,也无法验证它。
至于需要知道哪个方法首先被调用,所以你可以验证异常,你有几个选择:
答案 1 :(得分:2)
通常你只需要假物品,而不是嘲笑。模拟对象用于测试组件交互,通常可以通过直接查询SUT的状态来避免这种情况。模拟的最实际用途是测试与某些外部系统(数据库,文件系统,Web服务等)的交互,对于其他事项,您应该能够直接查询系统状态。