什么时候期待什么时候存根? [英] When to Expect and When to Stub?

查看:37
本文介绍了什么时候期待什么时候存根?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 NMock2,并起草了以下 NMock 类来表示一些常见的模拟框架概念:

I use NMock2, and I've drafted the following NMock classes to represent some common mock framework concepts:

  • Expect:这指定了一个模拟方法应该返回什么,并表示调用必须发生或测试失败(伴随着对 VerifyAllExpectationsHaveBeenMet() 的调用).

  • Expect: this specifies what a mocked method should return and says that the call must occur or the test fails (when accompanied by a call to VerifyAllExpectationsHaveBeenMet()).

Stub:指定模拟方法应返回的内容,但不会导致测试失败.

Stub: this specifies what a mocked method should return but cannot cause a test to fail.

那么我应该什么时候做呢?

So which should I do when?

推荐答案

很多mocking框架都带来了 mocks &存根更接近 &更接近于可以认为它们在功能上几乎相同的程度.然而,从概念的角度来看,我通常会尝试遵循这个约定:

A lot of mocking frameworks are bringing the concepts of mocks & stubs closer & closer together to the point that they can be considered functionally almost the same. From a conceptual perspective however, I usually try to follow this convention:

  • Mock:仅当您明确尝试验证被测对象的行为时(即您的测试表明该对象必须调用该对象).
  • 存根:当您尝试测试某些功能/行为,但为了使其正常工作,您需要依赖一些外部对象(即您的测试表明该对象必须做某事,但作为副作用,它可能会调用该对象)
  • Mock: Only when you are explicitly trying to verify the behaviour of the object under test (i.e. your test is saying that this object must call that object).
  • Stub: When you are trying to test some functionality/behaviour, but in order to get that working you need to rely on some external objects (i.e. your test is saying that this object must do something, but as a side effect, it may call that object)

当您确保每个单元测试只测试一件事时,这一点会变得更加清晰.当然,如果您尝试在一次测试中测试所有内容,那么您不妨期待所有内容.但是通过只期待特定单元测试正在检查的内容,您的代码会更加清晰,因为您可以一眼看出测试的目的是什么.

This becomes clearer when you make sure that each of your unit tests only test one thing. Sure if you try to test everything in one test then you might as well Expect everything. But by only expecting the things that specific unit test is checking for, your code is much clearer because you can see at a glance what the purpose of the test is.

这样做的另一个好处是,您将稍微远离变化和当更改导致中断时获得更好的错误消息.换句话说,如果您对实现的某些部分进行了细微的更改,则更有可能只破坏一个测试用例,这将准确地向您显示出什么被破坏,而不是一整套测试破坏&只是制造噪音.

Another benefit of this is that you'll be slightly more insulated from change & get better error messages when a change causes a break. In other words if you subtley change some part of your implementation, your more likely to get only one test case breaking, which will show you exactly what's broken, rather than a whole suite of tests breaking & just creating noise.

编辑:根据一个人为的示例,计算器对象审核所有添加到数据库中的所有内容(以伪代码形式)可能会更清楚...

Edit: It might be clearer based on a contrived example where a calculator object audits all additions to a database (in pseudo-code)...

public void CalculateShouldAddTwoNumbersCorrectly() {
    var auditDB = //Get mock object of Audit DB
    //Stub out the audit functionality...
    var calculator = new Calculator(auditDB);
    int result = calculator.Add(1, 2);
    //assert that result is 3
}

public void CalculateShouldAuditAddsToTheDatabase() {
    var auditDB = //Get mock object of Audit DB
    //Expect the audit functionality...
    var calculator = new Calculator(auditDB);
    int result = calculator.Add(1, 2);
    //verify that the audit was performed.
}

所以在第一个测试用例中,我们正在测试 Add 方法的功能 &不关心审计事件是否发生,但我们碰巧知道计算器在没有审计数据库引用的情况下将无法工作,因此我们只是将其存根以提供最少的功能来让我们的特定测试用例正常工作.在第二个测试中,我们专门测试当您执行 Add 时,审计事件会发生,所以这里我们使用期望(请注意,我们甚至不关心结果是什么,因为那不是我们正在测试什么).

So in the first test case we're testing the functionality of the Add method & don't care whether an audit event occurs or not, but we happen to know that the calculator won't work with out an auditDB reference so we just stub it out to give us the minimum of functionality to get our specific test case working. In the second test we're specifically testing that when you do an Add, the audit event happens, so here we use expectations (notice that we don't even care what the result is, since that's not what we're testing).

是的,您可以将这两种情况合二为一,&做预期并断言你的结果是 3,但是你在一个单元测试中测试两个案例.这会使您的测试更脆弱(因为有更大的表面积可能会改变以破坏测试)并且不太清楚(因为当合并的测试失败时,问题所在并不是很明显......添加不起作用,还是审计不起作用?)

Yes you could combine the two cases into one, & do expectations and assert that your result is 3, but then you're testing two cases in one unit test. This would make your tests more brittle (since there's a larger surface area of things that could change to break the test) and less clear (since when the merged test fails its not immediately obvious what the problem is.. is the addition not working, or is the audit not working?)

这篇关于什么时候期待什么时候存根?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆