Метод заглушки с параметром ArrayList / List завершается неудачно при использовании any () или anyList () - PullRequest
0 голосов
/ 31 мая 2019

У меня есть класс Java.

class Blah{
        public Blah(){

        }
        public String testMe(List<String> s){
            return new String("hello "+s.get(0));
        }


        public String testMeString(String s){
            return new String("hello "+s);
        }


    }

Я не могу успешно заглушить и протестировать метод testMe. Обратите внимание, что я просто пытаюсь понять насмешки в Java. Например я попробовал:

    @Test
    public void testTestMe(){
        Blah blah = spy(new Blah());
        ArrayList<String> l = new ArrayList<String>();
        l.add("oopsie");
        when(blah.testMe(Matchers.any())).thenReturn("intercepted");
        assertEquals("intercepted",blah.testMe(l));

Возвращает исключение NullPointerException. Я также пробовал любой (List.class), любой (ArrayList.class). Я также пытался использовать anyList(), но это дает мне ошибку IndexOutOfBounds. Что я делаю неправильно? Интересно, что мой testMeString работает нормально. Если я сделаю

@Test
    public void testTestMeString(){
        Blah blah = spy(new Blah());
        when(blah.testMeString(any())).thenReturn("intercepted");
        assertEquals("intercepted",blah.testMeString("lala"));
}

тесты проходят с любым () и любым (String.class).

Ответы [ 3 ]

3 голосов
/ 31 мая 2019

С этим оператором blah.testMe() включает в себя when(), он вызывает реальный метод:

when(blah.testMe(Matchers.any())).thenReturn("intercepted");

Чтобы избежать этого, вы должны использовать шаблон doReturn(...).when(...).methodToInvoke().

doReturn("intercepted").when(blah).testMe(Matchers.any()));

Вы заметили, что с этим синтаксисом: оператор blah.testMe() не указан нигде. Так что это не называется.

Помимо этого вопроса, я думаю, вам не нужен шпион для проверки этого метода.
Шпионаж - это очень специфический инструмент для имитации, который вы используете только тогда, когда у вас нет выбора: вам нужно смоделировать тестируемый объект, что является плохой практикой, и вы не можете реорганизовать реальный код.

Но здесь вы можете просто сделать:

@Test
public void testTestMe(){
    Blah blah = new Blah();
    ArrayList<String> l = new ArrayList<String>();
    l.add("oopsie");
    assertEquals("hello oopsie",blah.testMe(l));
 }
2 голосов
/ 31 мая 2019

Вам следует пересмотреть, используя spy, mock и т. Д., Эти средства следует использовать, когда у вас есть внешняя система, остальная веб-служба, БД, которую вы не хотите вызывать во время модульных тестов. В простых сценариях, подобных этому, просто создайте тестовый ввод и проверьте вывод.

@Test public void testTestMeString(){
 //given
  List<String> list = Arrays.asList("aaa");
 //when
 String result = blah.testMe(list);
 //then
 assertEquals(result, "hello aaa");
 }

Если вас интересует given, when, then отметьте BDD.

1 голос
/ 31 мая 2019

Ваше исключение NullPointerException генерируется во время заглушки , а не во время теста.

Это потому, что Matchers.any() на самом деле возвращает null, поэтому, если вы используете его, когда вывызывая реальный метод, вы передаете null в качестве аргумента.testMeString работает, потому что null + s не вызывает исключение NullPointerException (вместо него используется строка "null").

Вместо:

when(blah.testMe(any())).thenReturn("intercepted");

Вам необходимо использовать

doReturn("intercepted").when(blah).testMe(any());

Это задокументировано (хотя, по общему признанию, не очень ясно) как Важное замечание по шпионажу реальных объектов! в документации Mockito.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...