Как проверить пустую функцию с последовательными вызовами - PullRequest
0 голосов
/ 28 июня 2018

Как можно протестировать функцию, которая не возвращает значение, но использует заданные аргументы для построения некоторых значений, которые отправляются в последовательную функцию?

Например

public void handleSomeEvent(String str1, String str2){
   MyObject obj1 = new MyObject();
   obj1.setParameterA(str1);
   obj2.setParameterB(str2);
   EventHandler.getInstance().notify(obj1)
}

В приведенном выше примере я хотел бы убедиться, что EventHandler.notify был вызван с объектом, содержащим str1 как parameterA и str2 как parameter2. Можно ли это сделать с помощью какой-нибудь общей насмешливой рамки (т.е. mockito)?

Ответы [ 3 ]

0 голосов
/ 28 июня 2018

В случаях, когда необходимо проверить вызываемые паррамы, используйте ArgumentCaptor<T> от Mockito

См. Ссылку: https://static.javadoc.io/org.mockito/mockito-core/2.6.9/org/mockito/ArgumentCaptor.html

0 голосов
/ 03 июля 2018

Unittest проверки публичное наблюдаемое поведение , где «публичный» означает через API единиц измерения и «поведение», означающее возвращаемые значения и / или связь с зависимости .

Ваш код имеет скрытую зависимость , вызванную статическим доступом к объекту EventHandler. Я предполагаю, что ваш EventHandler класс включает в себя образец Java-синглтона . Это код STUPID , с которого большинство из нас начали.

Вы не должны отказываться от этого плохого дизайна, используя PowerMock .

Лучше было бы передать объект EventHandler в качестве параметра конструктора в тестируемый код следующим образом:

    class MyTestedClass{
       private final EventHandler eventHandler;
       class MyTestedClass(EventHandler eventHandler){
          this.eventHandler=eventHandler;
       }

       public void handleSomeEvent(String str1, String str2){
          MyObject obj1 = new MyObject();
           obj1.setParameterA(str1);
           obj2.setParameterB(str2);
           eventHandler.notify(obj1)
        }
    }

А затем сделайте ваш EventHandler нормальным классом, от которого вы можете наследовать. (хотя бы удалите ключевое слово final из объявления класса).

Тогда вы могли бы использовать обычный Mockito для замены объекта EventHandler тестовым двойником и проверки связи ваших кодов с этим двойным тестом:

    class MyTestedClassTest{
       @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); 
       @Mock private EventHandler eventHandler; // ignores the private constructor
       class MyTestedClass(EventHandler eventHandler){
          this.eventHandler=eventHandler;
       }

       @Test
       public void notifiesEventHandlerWithDTO(String str1, String str2){

           new UnderTest(eventHandler).handleSomeEvent("test1","test2");

           ArgumentCaptor<MyObject> handlerArg = ArgumentCaptor.forClass(MyObject.class);
           verify(eventHandler).notify(handlerArg.capture());
           assertThat("parameter A passed to object",
                       handlerArg.getValue().getParameterA(),
                       equalTo("test1"));
           assertThat("parameter B passed to object",
                       handlerArg.getValue().getParameterB(),
                       equalTo("test2"));
        }
    }
0 голосов
/ 28 июня 2018

Вы можете сделать следующее

@RunWith(PowerMockRunner.class)
@PrepareForTest({ EventHandler.class })
public class UnderTestTest {

@Test
public void testLoadUniqueOrNull() throws NKFException {
    PowerMockito.mockStatic(EventHandler.class);

    EventHandler handler = PowerMockito.mock(EventHandler.class);
    PowerMockito.when(EventHandler.getInstance())
            .thenReturn(handler);

    ArgumentCaptor<MyObject> handlerArg = 
    ArgumentCaptor.forClass(MyObject.class);
    PowerMockito.doNothing()
            .when(handler)
            .notify(handlerArg.capture());

    new UnderTest().handleSomeEvent("test");
    Assert.assertEquals(new MyObject("test"), handlerArg.getAllValues()
            .get(0));
}

}


public class UnderTest {
    public void handleSomeEvent(String str1) {
        MyObject obj1 = new MyObject(str1);

        EventHandler.getInstance()
                .notify(obj1);
    }
}


public class MyObject {

    private final String x;

    public MyObject(String x) {
        this.x = x;
    }

    @Override
    public boolean equals(Object obj) {
        return ((MyObject) obj).x == x;
    }
}


public class EventHandler {

    private final static EventHandler e = new EventHandler();

    public static EventHandler getInstance() {
        return e;
    }

    public void notify(MyObject obj) {
        // whatever
    }
}

(примечание: этот быстрый код предназначен для демонстрации функциональности, а не передовых методов кодирования)

...