简体   繁体   English

尝试部分模拟void方法时,我得到NotAMockException - 我做错了什么?

[英]I get NotAMockException when trying to partially mock a void method - what am I doing wrong?

I'm trying to use two Mockito patterns together: 我试图一起使用两个Mockito模式:

  • For partially mocking, use Mockito.spy . 对于部分Mockito.spy ,请使用Mockito.spy
  • For mocking methods which return void, use Mockito.doXXX(...).when(mock).method(matchers) , because you can't use Mockito.when(mock.method(matchers)) syntax for obvious reasons ( method returns void so can't be passed as an argument) 对于返回void的Mockito.doXXX(...).when(mock).method(matchers)方法,使用Mockito.doXXX(...).when(mock).method(matchers) ,因为你不能使用Mockito.when(mock.method(matchers))语法,原因很明显( method返回void,因此不能作为参数传递)

When combining them, I am facing a NotAMockException . 组合它们时,我面临NotAMockException Below is a (contrived) example which I tested using PowerMockito 1.6.2 (=Mockito 1.10.19) and JUnit 4.12, and reproduces the problem. 下面是一个(人为的)示例,我使用PowerMockito 1.6.2(= Mockito 1.10.19)和JUnit 4.12进行了测试,并重现了该问题。

public class Greeter { // this is the class we will be partially mocking
    public void helloWorld(String hello, Set<String> set) {
        set.add("Hello: "+hello);
    }

    public void goodbyeWorld(String goodbye, Set<String> set) {
        set.add("Goodbye: "+goodbye);
    }
}

public class ExampleClass { // this is the class under test
    public String helloGoodbye(String input, Greeter greeter) {
        Set<String> helloSet = new HashSet<String>();
        Set<String> goodbyeSet = new HashSet<String>();
        greeter.helloWorld(input, helloSet);
        greeter.goodbyeWorld(input, goodbyeSet);
        return (helloSet.iterator().next() + ", " + goodbyeSet.iterator().next());
    }
}

public class ExampleClassTest {
    @Test
    public void test() {
        Greeter greeter = new Greeter();
        Mockito.spy(greeter);
        Mockito.doAnswer(new Answer(){ // exception thrown points to this line
            @Override
            public Void answer(InvocationOnMock invocation) throws Throwable {
                ((Set<String>)invocation.getArguments()[1]).add("Bonjour: " + invocation.getArguments()[0]);
                return null;
            }
        }).when(greeter).helloWorld(Mockito.any(String.class), Mockito.any(Set.class));

        ExampleClass example = new ExampleClass();
        String aggregateGreeting = example.helloGoodbye("Mars", greeter);
        Assert.assertEquals("Bonjour: Mars, Goodbye: Mars", aggregateGreeting);
    }
}

Here is the full error I get: 这是我得到的完整错误:

org.mockito.exceptions.misusing.NotAMockException: 
Argument passed to when() is not a mock!
Example of correct stubbing:
    doThrow(new RuntimeException()).when(mock).someMethod();
    at com.example.ajb.pmv.ExampleClassTest.test(ExampleClassTest.java:21)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:211)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)


Process finished with exit code -1

Any workarounds (other ways to achieve the goal of mocking a single void method within a class) would also be welcome!! 任何变通办法(其他方法来实现在类中模拟单个void方法的目标)也将受到欢迎!

You're not passing the spy to when() . 你没有把间谍传递到when() You're passing the original object. 你正在传递原始对象。

Change the line 改变线

Mockito.spy(greeter);

to

greeter = Mockito.spy(greeter);

Mockito.spy() creates a spy object that is a copy of the original object. Mockito.spy()创建一个间谍对象,它是原始对象的副本。 It doesn't modify the original object. 它不会修改原始对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM