我应该在测试方法中模拟本地方法调用吗? [英] Should I mock local method invocation inside a tested method?

查看:49
本文介绍了我应该在测试方法中模拟本地方法调用吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我关于单元测试概念的问题:

My question about the concept of unit testing:

class A {
   public void m1() {
      // code
      m2();
      //code
   }

   public void m2() {
      //some code
   }

}

根据最佳实践,我应该如何测试 m1 方法?单元是类还是单元是方法?

According to best practices, how should I test the m1 method? Is the unit the class or is the unit the method?

我的观点 - 我应该单独测试 m2 而我不应该测试 m1m2 集成.

My view - I should test m2 separately and I shouldn't test m1 and m2 integration.

使用我的观点已经够难了——我应该使用复杂的框架进行测试并使用非常现代的东西.

To use my view is hard enough - I should use sophisticated frameworks for testing and use very modern things.

按照我对单元测试的理解,测试应该很简单!如果你的代码很好,你可以不用复杂的东西来测试它.但是在 m1() 内部调用 m2() 是正常代码.

According to my sense of unit testing, tests should be simple! If your code is good, you can test it without sophisticated things. But invoking m2() inside m1() is normal code.

请澄清我的误解.

模拟示例(伪代码):

//prepare
A testClass = mock(A.class);
when(testClass.m2()).doNothing();
when(testClass.m1()).callRealMethod();
//execute:
testClass.m1();
//verify
check testClass state after method m1 invocation.

这就是我测试模拟类的方式.这正常吗?

This is how I test a mocked class. Is this normal?

推荐答案

首先,当您进行单元测试时,测试所有公共方法.在您的示例中,m1m2 是公开的,因此您将对两者进行测试.

First, when you unit-test, test all public methods. In your example m1 and m2 are public, so you'd have tests for both.

您可能想要存根或模拟 m2 的几个原因:

There are several reasons that you might want to stub or mock m2:

  1. 如果在测试 m1 时遇到任何问题,因为 m1 调用 m2、存根或模拟 m2.您可能会遇到的一些问题:

  1. If, when you test m1, you encounter any problems because m1 calls m2, stub or mock m2. Some problems you might encounter:

  • m2 可能会调用外部服务
  • m2 可能只是很慢
  • 使用满足 m2 的参数调用 m1 可能很困难(你的 m2 没有参数,但我说的是一般)
  • m2 might call external services
  • m2 might just be slow
  • it might be difficult to call m1 with parameters that satisfy m2 (your m2 has no parameters, but I'm speaking generally)

有时候,当你测试一个调用另一个方法的方法,同时也测试另一个方法时,你会发现两个方法的测试之间存在重复——调用方法的一些测试真的是在测试被调用的方法.通过在调用方法中存根或模拟调用方法来处理这个问题,测试调用方法足以证明被调用方法被调用,并彻底测试被调用方法.

Sometimes, when you test a method that calls another method and also test the other method, you find that there is duplication between the tests of the two methods -- some of the tests of the calling method are really testing the called method. Deal with that by stubbing or mocking the called method out of the calling method, testing the calling method just enough to prove that the called method is called, and thoroughly testing the called method.

如果你做 TDD,你可能会先写 m1,然后再写 m2.然后,您将存根或模拟 m2,以便您对 m1 的测试通过,然后继续测试和编写 m2.

If you do TDD, you might write m1 before you write m2. You would then stub or mock m2 so that your tests of m1 would pass, and then go on to test and write m2.

但如果您没有任何理由存根或模拟 m2,请不要这样做.一个方法以不需要存根或模拟的方式调用其他方法是常见且合理的.被调用的方法可能简短而简单,或者调用方法可能只是为了可读性而被分解成一堆辅助方法.如果被调用的方法在另一个类中,情况也是如此(因为它被多个调用方法使用);如果它通过调用它的方法的测试完全测试,并且如果测试之间没有重复,则不需要存根或模拟.

But if you don't have any reason to stub or mock m2, don't. It is common and reasonable for a method to call other methods in ways that don't require stubbing or mocking. The called methods might be short and simple, or the calling method might just be broken up into a bunch of subsidiary methods for readability. That's even true if the called method is in another class (because it's used by more than one calling method); if it is fully tested by tests of methods that call it, and if there is no duplication between tests, there is no need to stub or mock.

上面模拟 m2 而不运行 m1 的例子是一件非常正常的事情,它完成了工作,但由于 Mockito 接管了所有类的方法.你可以用 Mockito 间谍做得更好,这里讨论:使用时嘲笑和间谍有什么区别Mockito?.

The example above of mocking m2 without running m1 is a perfectly normal thing to want to do and it gets the job done, but it's ugly since Mockito takes over all of a class's methods. You can do it more nicely with a Mockito spy, discussed here: What is the difference between mocking and spying when using Mockito?.

A a = spy(new A());
doNothing().when(spy).m2();
a.m1();
# check state of a

这篇关于我应该在测试方法中模拟本地方法调用吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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