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

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

问题描述

我使用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?

推荐答案

许多模拟框架都带来了模拟&的概念.存根更紧密地联系到可以认为它们在功能上几乎相同.但是,从概念上讲,我通常尝试遵循以下约定:

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: 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方法&的功能.不在乎是否发生审核事件,但是我们碰巧知道计算器无法在没有auditDB引用的情况下工作,因此我们只是将其存根以提供使我们的特定测试用例正常工作的最少功能.在第二个测试中,我们专门测试当您执行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天全站免登陆