【问题标题】:org.mockito.exceptions.misusing.MissingMethodInvocationException: when() requires an argument which has to be 'a method call on a mock'org.mockito.exceptions.misusing.MissingMethodInvocationException: when() 需要一个参数,该参数必须是“模拟方法调用”
【发布时间】:2017-05-08 08:42:23
【问题描述】:

我开发了一个带有控制器的 spring 示例项目,并在其中调用了一个静态方法。

当我尝试运行代码时,它会导致我出现异常。

LoginController .java

@Controller
public class LoginController {@ResponseBody
@RequestMapping(value="/login")
public String login(){
    System.out.println("in login method");
    String s = SampleClass.method();
    System.out.println("String value :  "+s);
    return "welcome to login page";
}}

SampleClass.java

public class SampleClass {

public static String method(){
    System.out.println("in static method");
    return "static method";
}}

LoginControllerTest.java

@PrepareForTest(SampleClass.class)
public class LoginControllerTest {

private MockMvc mockMvc;

@InjectMocks
private LoginController loginController;


@Before
public void setUp() {

    System.out.println("in setup");
    PowerMockito.mockStatic(SampleClass.class);

    MockitoAnnotations.initMocks(this);
    mockMvc = MockMvcBuilders.standaloneSetup(loginController).build();
    System.out.println("setupdone");

}

@Test
public void loginTest() throws Exception{
    System.out.println("in login test");
    PowerMockito.when(SampleClass.method()).thenReturn("hello");
    mockMvc.perform(get("/login"))
    //.andDo(print())
    .andExpect(status().isOk());
    System.out.println("test completed");
}}

错误

org.mockito.exceptions.misusing.MissingMethodInvocationException: when() 需要一个参数,该参数必须是“模拟方法调用”。 例如: when(mock.getArticles()).thenReturn(articles);

此外,出现此错误的原因可能是: 1.你存根:final/private/equals()/hashCode()方法。这些方法不能被存根/验证。模拟方法 不支持在非公共父类上声明。 2. 在 when() 中,你不会在 mock 上调用方法,而是在其他对象上调用。

在 org.powermock.api.mockito.PowerMockito.when(PowerMockito.java:495) 在 com.junit.example.controller.LoginControllerTest.setUp(LoginControllerTest.java:57) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(未知来源)在 java.lang.reflect.Method.invoke(未知来源)在 org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) 在 org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 在 org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) 在 org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24) 在 org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) 在 org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) 在 org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) 在 org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) 在 org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) 在 org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) 在 org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) 在 org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) 在 org.junit.runners.ParentRunner.run(ParentRunner.java:309) 在 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:459) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

谁能帮我解决一下?

【问题讨论】:

    标签: java spring mockito junit4


    【解决方案1】:

    你为什么要让你的测试变得复杂?,当你可以简单地把它写成:

    import static org.junit.Assert.assertEquals;
    import org.junit.Before;
    import org.junit.Test;
    import org.mockito.InjectMocks;
    import org.mockito.MockitoAnnotations;
    
    import com.arpit.controller.LoginController;
    
    public class LoginControllerTest {
    
        @InjectMocks
        private LoginController loginController;
    
        @Before
        public void setupMock() {
            MockitoAnnotations.initMocks(this);
        }
    
        @Test
        public void loginTest() {
            String val = loginController.login();
            assertEquals("welcome to login page", val);
        }
    }
    

    控制台输出:

    in login method
    in static method
    String value :  static method
    

    【讨论】:

    • PowerMock 在您尝试模拟静态方法时使用。最初的问题是试图模拟从静态上下文调用的 SampleClass.method() 。这就是测试采用这种结构的原因。
    【解决方案2】:

    根据文档,您没有正确使用它: https://github.com/powermock/powermock/wiki/MockitoUsage

    来自文档:

    1. @PrepareForTest(Static.class)注释类(你没有这样做)
    2. 调用 mockStatic PowerMockito.mockStatic(Static.class);
    3. 使用Mockito.when()。您正在使用PowerMockito.when()

    【讨论】:

    • 他正在调用PrepareForTest,而PowerMockito.when 的一个参数只是对Mockito.when 的转发,因为PowerMockito 添加了一些重载,您将无法静态导入@987654330 @ 来自两个类,除非你使用 Groovy,所以问题仍然存在,问题出在哪里。
    • 这个答案已经有两年多了,所以我完全不记得了。我可能在这里犯了一个错误,但奇怪的是我会错过这个并且得到两个赞成票。编辑历史没有显示 PrepareForTest 曾经丢失过。
    • 这一点也不奇怪。您描述了有效的可能问题。至少有两个用户有您描述的错误,因此对您的答案表示赞同。但这并不意味着它与 OP 有任何相关性,尤其是在答案未被接受的情况下。在当前状态下,它对实际问题并没有真正的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-29
    • 2020-05-12
    • 2010-09-23
    • 1970-01-01
    • 2021-12-18
    相关资源
    最近更新 更多