Mockito аргумент соответствия для java 8 функций - PullRequest
0 голосов
/ 12 апреля 2020

Я хочу смоделировать метод, который принимает функцию в качестве ввода. И функция, которую я хочу протестировать, использует несколько функций с разными типами возвращаемых значений. Есть ли способ издеваться над такого рода функциями.

Это мои классы

public class Visitor {

    public <T> Function<String, T> visit(Function<Integer,T> transformer){
        return (input) -> {
            //Actual one has some complex code including I/O operations
            //To understand easily, added following lines
            int length = input.length();
            return transformer.apply(length);
        };
    }
}
public class Demo {
    private Visitor visitor;

    public Demo(Visitor visitor) {
        this.visitor = visitor;
    }

    public String demoFunction(){
        String input = "some input";
        String strOutput = visitor.visit(length -> {
          // Actual  actual code has multiple lines.
          // Added this line to understand functionality easily
         return Integer.toString(length);
         }).apply(input);
        Boolean boolOutput = visitor.visit(length -> length%2==0).apply(input);
        // other operations
        return strOutput+","+boolOutput;

    }
}

После ссылки этот реализовал этот тестовый пример

public class DemoTest {

    @Test
    public void demoFunctionTest() {
        Visitor visitor = Mockito.mock(Visitor.class);
        Mockito.when(visitor.visit(Matchers.<Function<Integer, String>>any())).thenReturn(s -> "1");
        Mockito.when(visitor.visit(Matchers.<Function<Integer, Boolean>>any())).thenReturn(s -> true);

        Demo demo = new Demo(visitor);
        demo.demoFunction();
    }
}

Но это не удалось при запуске теста. Это исключение, которое я получил.

java.lang.ClassCastException: java.lang.Boolean cannot be cast to java.lang.String

at com.raghumolabanti.demo.Demo.demoFunction(Demo.java:15)
at com.raghumolabanti.demo.DemoTest.demoFunction(DemoTest.java:19)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
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:68)

Обновление: На самом деле мой код сложен и в некоторых местах включает в себя ввод-вывод. Было бы сложно включить оригинальный код. Чтобы дать простой рабочий код, я создал эти примеры классов.

Ответы [ 2 ]

1 голос
/ 12 апреля 2020

Вот почему мы хотим смоделировать функцию, когда в этом нет необходимости. Макет нужен, когда включены бизнес-логика или сделаны какие-либо сетевые вызовы (Шаблон отдыха) и т. Д. c. В этом случае вы можете просто выполнить код и получить ссылку, а затем проверить его значение.

Несколько вещей, замеченных в вашем тестовом примере.

  • Этот метод не требует ввода / нет возвращаемых значений. Означает, что это вспомогательный метод. в таких случаях вы можете смоделировать место, где вы вызываете этот метод, вместо этого насмехаясь внутри этой функции
  • Вы можете сделать так, чтобы эта функция принимала входной параметр и возвращала список значений, которые вам нужно проверить, а затем используйте assertMatchers для проверки вашего результата.

На более легкой ноте Mockito - это мощный инструмент, и если мы будем смеяться над каждым объектом и строками, тогда не будет правильного написания контрольных примеров, потому что все проверено и что нужно проверять!

0 голосов
/ 12 апреля 2020

Экземпляры параметра функции в классе Visitor просты в создании и могут не стоить насмехаться.

Текущий код тестирования:

Mockito.when(visitor.visit(Matchers.<Function<Integer, String>>any())).thenReturn(s -> "1");
visitor.visit(length -> Integer.toString(length)).apply(input);

может быть просто заменен на:

visitor.visit(length -> 1).apply(input);

Тогда это будет вопрос заставить Demo выставить результат применение посетителя для его проверки.

Это было бы намного надежнее, чем попытка учесть каждый тип T из Function<Integer, T>, который можно передать, а затем вручную указать поведение.

Ссылка: Не переусердствуйте с издевательствами

...