【问题标题】:Mock that a method call was attempted during unit test, but do not actually call it模拟在单元测试期间尝试了方法调用,但实际上并未调用它
【发布时间】:2012-02-25 17:00:09
【问题描述】:

我正在编写 JUnit 测试并使用 Mockito,我想调用一个方法,该方法又多次调用第二个方法。我不希望在我的单元测试期间调用第二种方法,但我想知道它的参数是什么。我要测试的代码如下所示:

public class MyClass {
    public void myMethod() {
        int a = [do some logic]
        int b = [do some logic];
        doSomething(a, b);

        a = [do some logic];
        b = [do some logic];
        doSomething(a, b);
    }

    public void doSomething(int a, int b) {
        // code that I do not want to be executed during a unit test
    }
}

现在是单元测试:

@Test
public void test() {
    MyClass myClass = new MyClass();
    myClass.myMethod();
    verify(myClass).doSomething(17, 33);
    verify(myClass).doSomething(9, 18);
}

我是 Mockito 的新手,我不知道是否有可能 A) 阻止 doSomething() 被执行和 B) 验证 a & b 参数的值。我愿意接受诸如“Mockito 无法帮助您”或“这在技术上不可行”之类的答案。如果没有办法模拟这种事情,我可能会考虑将那些 [do some logic] 块重构为我可以直接测试的方法,但我的代码比这个简单的例子更复杂,我不允许在线发布代码.

【问题讨论】:

标签: java methods junit mocking call


【解决方案1】:

间谍很丑。如果你部分地模拟你的测试类,你很容易对模拟什么和真正测试什么感到困惑。 Mockito 的 Javadoc 明确警告不要进行部分模拟。

最好重构你的代码,这样你就可以干净地测试它。将doSomething() 提取到一个新类中:

public class SomethingDoer {
    public void doSomething(int a, int b) {
        // code that you do not want to be executed during a unit test
    }
}

更改了我的班级:

public class MyClass {
    private final SomethingDoer somethingDoer;

    public MyClass(SomethingDoer somethingDoer) {
        this.somethingDoer = somethingDoer;
    }

    public void myMethod() {
        int a = [do some logic]
        int b = [do some logic];
        somethingDoer.doSomething(a, b);

        a = [do some logic];
        b = [do some logic];
        somethingDoer.doSomething(a, b);
    }
}

测试:

@Test
public void test() {
    SomethingDoer somethingDoer = mock(SomethingDoer.class);
    MyClass myClass = new MyClass(somethingDoer);
    myClass.myMethod();
    verify(somethingDoer).doSomething(17, 33);
    verify(somethingDoer).doSomething(9, 18);
}

【讨论】:

  • +1:虽然我很乐意大致介绍如何进行部分模拟,但这样做是个好建议。
  • 无论如何,我最终不得不将doSomething() 重构为一个新类,原因不同。所以很自然,这就是我采用的解决方案,但对两者都有看法是件好事。
【解决方案2】:

为此,您需要Mockito partial mock

这是未经测试的,但我认为您想要的可能类似于:

@Test
public void test() {
    MyClass myClass = spy(new MyClass());
    doNothing().when(myClass).doSomething(any(Integer.class), any(Integer.class));
    myClass.myMethod();
    verify(myClass).doSomething(17, 33);
    verify(myClass).doSomething(9, 18);
}

spy设置了部分mock,这样可以替换一些方法,使用一些真实的方法。 doNothing 存根你的 doSomething(一个有趣的命名巧合)不做任何事情,而不是调用真正的代码。

【讨论】:

  • 成功!但是我得到了 NullPointerException 一段时间,在试图根除它的同时学到了很多关于间谍和存根的知识。 NPE 是由any(Integer.class) 引起的。必须用Mockito.anyInt() 替换它,然后瞧。诡异的。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多