заглушка двух методов в макете вызывает исключение с использованием Mockito и Spring MockMVC

Я пытаюсь настроить простое модульное тестирование MVC. Я пытаюсь выполнить следующее:

  • Используйте Spring MockMVC для проверки состояния HTTP и данных HTTP, возвращаемых моими контроллерами.
  • Мои контроллеры имеют ссылку Autowired на фасад, который выполняет реальную логику.
  • Итак, я создаю один тестовый класс для тестирования одного контроллера.
  • Я хочу протестировать два метода этого контроллера, поэтому я создал два метода в своем тестовом классе.
  • Я издевался над своим фасадом и вводил его в свой контроллер.
  • Итак, я хочу настроить этот макет с возвратом каждого из методов, которые я тестирую.

Я использую следующий код:

public class LoginTest {

    MockMvc mockMvc;

    @Mock
    Cadastre facade;

    @InjectMocks
    Login controller;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        Mockito.when(facade.login(Mockito.any(String.class))).thenReturn(true);
        Mockito.when(facade.getUser(Mockito.any(String.class))).thenReturn(Mockito.any(UserData.class));

        mockMvc = MockMvcBuilders.standaloneSetup(controller).setMessageConverters(new MappingJackson2HttpMessageConverter()).build();
    }

    @Test
    public void thatLoginUsesStatusOK() throws Exception {
        this.mockMvc.perform(MockMvcRequestBuilders.get(UserFixtures.loginUrl())).andExpect(MockMvcResultMatchers.status().isOk());
    }

    @Test
    public void thatUserDataUsesStatusOK() throws Exception {
        this.mockMvc.perform(MockMvcRequestBuilders.get(UserFixtures.getUserDataUrl())).andExpect(MockMvcResultMatchers.status().isOk());
    }
}

Если я попытаюсь выполнить этот тестовый класс, произойдет сбой с ошибкой:

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
Invalid use of argument matchers!
1 matchers expected, 2 recorded:
-> at com.example.test.api.login.LoginTest.setup(LoginTest.java:38)
-> at com.example.test.api.login.LoginTest.setup(LoginTest.java:39)

This exception may occur if matchers are combined with raw values:
    //incorrect:
    someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
    //correct:
    someMethod(anyObject(), eq("String by matcher"));

For more info see javadoc for Matchers class.

    at com.example.test.api.login.LoginTest.setup(LoginTest.java:39)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

Если я перемещаю каждую строку с имитируемым методом (строки Mock.when) внутри своего метода test() и вызываю эти методы тестирования отдельно, они работают. Но если я попытаюсь выполнить весь класс, то сработает только один из методов test(), а другой выдаст следующее исключение (которое, похоже, имеет ту же причину, что и выше):

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
Misplaced argument matcher detected here:

-> at com.example.test.api.login.LoginTest.thatLoginUsesStatusOK(LoginTest.java:45)

You cannot use argument matchers outside of verification or stubbing.
Examples of correct usage of argument matchers:
    when(mock.get(anyInt())).thenReturn(null);
    doThrow(new RuntimeException()).when(mock).someVoidMethod(anyObject());
    verify(mock).someMethod(contains("foo"))

Also, this error might show up because you use argument matchers with methods that cannot be mocked.
Following methods *cannot* be stubbed/verified: final/private/equals()/hashCode().

    at com.example.test.api.login.LoginTest.setup(LoginTest.java:37)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

Итак, я считаю, что причина в том, что я, вероятно, не очень хорошо понимал, как использовать Mockito. Не могли бы вы указать мне правильное направление?

Большое спасибо!


person Eduardo Lima    schedule 03.02.2014    source источник


Ответы (1)


Твоя проблема в том, где ты пишешь

thenReturn(Mockito.any(UserData.class))

Метод any предназначен для сопоставления значений, которые появляются во время теста, а не для создания значений. Вам нужно указать, какой объект UserData нужно вернуть, предположительно, создав экземпляр и передав его сюда.

person Dawood ibn Kareem    schedule 03.02.2014