首先,我不得不说,我是新手。所以也许我遗漏了一点。

我也刚刚开始习惯于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;
}

如果要测试此方法的错误处理,则必须知道首先调用哪个方法。但是我不想在编写测试时就被实施细节所困扰。

我想念什么吗?

最佳答案

您有2个选择。如果该方法会导致类中的某些更改,则可以改为测试该方法的结果。因此,您可以先调用CreateAandB(true,false)然后再调用其他方法来查看是否创建了正确的东西。在这种情况下,您的模拟对象可能是仅提供一些数据的存根。

如果doaAdoaB是注入到您的类中的对象,它们实际上在DB或类似数据库中创建数据,而您无法在测试中验证结果,那么您想测试与它们的交互,在这种情况下,您可以创建模拟并设置期望值,然后调用该方法并验证是否满足期望值。在这种情况下,您的模拟对象将是模拟对象,并将验证预期的行为。

是的,您正在测试实现细节,但是您正在测试方法是否正确使用其依赖关系的详细信息(这是您要测试的内容,而不是方法如何使用它们的依赖关系),而这些细节并不是您真正感兴趣的。

编辑

IDao daoA = MockRepository.GenerateMock<IDao>(); //create mock
daoA.Expect(dao=>dao.Create); //set expectation

...

daoA.VerifyExpectations(); //check that the Create method was called

您可以确保期望按特定顺序发生,但不使用我相信的AAA语法(source from 2009可能已经更改, EDIT see here对于可能适用于的选项),但是似乎有人开发了一种方法,可能允许这个here。我从未使用过,也无法验证。

至于需要知道首先调用哪个方法,以便可以验证异常,您有两种选择:
  • 在您的异常中有不同的消息,然后检查以确定是否引发了异常。
  • 除了期望异常之外,还期望对daoA的调用。如果您没有接到daoA的电话,则测试将失败,因为必须是第一个例外。
  • 10-08 16:41