Java Mockito Spy doReturn调用原始方法

Java Mockito Spy doReturn调用原始方法,java,junit,mockito,junit4,Java,Junit,Mockito,Junit4,我是莫基托的新手。我知道spy对象永远不会调用doReturn的原始方法,而是在我的代码中,这是不会发生的 import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Mockito.spy; import org.junit.Before; import org.junit.Test; import org.junit.runner.R

我是莫基托的新手。我知道spy对象永远不会调用
doReturn
的原始方法,而是在我的代码中,这是不会发生的

import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.spy;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;

class MyClass {
    public int method1(){
        int x =10;
        x = method2(2);
        return x;
    }

    public int method2(int y){
        method3();
        return 20;
    }

    public int method3(){
       return 30;
    }
}

@RunWith(MockitoJUnitRunner.class)
public class Method1Test {
    private MyClass myClass = new MyClass();

    @Before
    public void setup(){}

    @Test
    public void test01(){
        MyClass spyMyClass = spy(myClass);
        doReturn(28).when(spyMyClass).method2(any());
        int a = spyMyClass.method1();
        assertTrue("We did it!!!",a==20);
    }
}
下面是错误堆栈跟踪:

java.lang.NullPointerException 在com.Method1Test.test01(Method1Test.java:45) 在sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)处 位于sun.reflect.NativeMethodAccessorImpl.invoke(未知源) 在sun.reflect.DelegatingMethodAccessorImpl.invoke处(未知源) 位于java.lang.reflect.Method.invoke(未知源) 位于org.junit.runners.model.FrameworkMethod$1.runReflectVeCall(FrameworkMethod.java:50) 位于org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 位于org.junit.runners.model.FrameworkMethod.invokeeexplosive(FrameworkMethod.java:47) 位于org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 位于org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) 位于org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) 位于org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) 位于org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) 位于org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 位于org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 位于org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 访问org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 位于org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 位于org.junit.runners.ParentRunner.run(ParentRunner.java:363) 位于org.mockito.internal.runners.junit45和higherrunnerimpl.run(junit45和higherrunnerimpl.java:37) 位于org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62) 位于org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) 位于org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 位于org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538) 位于org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760) 位于org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460) 位于org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)


请有人帮我解决上述问题,并为我提供上述问题的解决方案。

该问题是由于传递给
method2
的参数类型不匹配造成的。这就是异常消息的这一部分告诉您的:

org.mockito.exceptions.misusing.invalidUseofMatchers异常: 此处检测到放错位置的参数匹配器:

以下测试通过:

@Test
public void test01(){
    MyClass spyMyClass = spy(myClass);
    doReturn(28).when(spyMyClass).method2(anyInt());
    int a = spyMyClass.method1();
    assertTrue("We did it!!!",a==28);
}
这里有两个变化:

  • 使用
    anyInt()
    而不是
    any()
  • 断言
    a==28
    ,因为您告诉存根返回
    28

  • 大家好,欢迎来到Stackoverflow。你能粘贴整个Junit测试类(包括导入)吗?你打算怎么做?我看到你把它打成28,但断言它会返回20。你期望的是什么?@GuillaumeS我已经添加了进口,请检查above@Dean你能告诉我为什么我会在stacktrace上获得NPE吗?为什么上面的doReturn调用上面的spy对象的原始方法?鉴于消息的内容是“我们做到了!!”,他可能希望它失败。我有一个疑问:假设我的方法具有类似于此的公共int method2(Foo-Foo),那么我可以传递为:doReturn(28)。when(spyMyClass)。method2(foomocobj)??如果您阅读完整的异常消息,您将看到Mockito的作者完全预料到了这种情况:“如果最后一个匹配器返回一个类似any()的对象,则此消息可能出现在NullPointerException之后,但存根方法签名需要一个基元参数,在这种情况下,请使用基元替代项。当(mock.get(any());//错误使用,将在(mock.get(anyInt()));//正确使用时引发NPE”因此,您遇到的问题是使用非特定对象匹配器-
    any()
    -作为基元参数的结果。如果您的参数从基元更改为,例如
    Foo
    ,则这将不适用。
    @Test
    public void test01(){
        MyClass spyMyClass = spy(myClass);
        doReturn(28).when(spyMyClass).method2(anyInt());
        int a = spyMyClass.method1();
        assertTrue("We did it!!!",a==28);
    }