Тестирование Java улучшено для поведения с Mockito - PullRequest
13 голосов
/ 17 июня 2011

Я хочу протестировать Java-метод, в котором есть улучшенный метод, с использованием Mockito.Проблема в том, что, когда я не знаю, как установить ожидания для улучшенного, чтобы работать.Следующий код был получен из неотвеченного вопроса в группе Google mockito :

import static org.mockito.Mockito.when;
import static org.testng.Assert.assertTrue;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.mockito.Mockito;
import org.testng.annotations.Test;

public class ListTest
{

  @Test
  public void test()
  {
    List<String> mockList = Mockito.mock(List.class);
    Iterator<String> mockIterator = Mockito.mock(Iterator.class);

    when(mockList.iterator()).thenReturn(mockIter);
    when(mockIter.hasNext()).thenReturn(true).thenReturn(false);
    when(mockIter.next()).thenReturn("A");

    boolean flag = false;
    for(String s : mockList) {
        flag = true;
    }
    assertTrue(flag);
  }
} 

Код внутри цикла for никогда не выполняется.Установка ожиданий для итератора не работает, потому что улучшенная версия Java не использует внутренний итератор списка.Установка ожиданий для метода List.get() тоже не подходит, поскольку расширенная реализация, похоже, тоже не вызывает метод get() из списка.

Любая помощь будет высоко ценится.

Ответы [ 4 ]

25 голосов
/ 17 июня 2011

У меня издевательство над итератором работает. Смотрите пример кода ниже:

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.util.Collection;
import java.util.Iterator;

import org.junit.Before;
import org.junit.Test;

public class TestMockedIterator {

    private Collection<String> fruits;
    private Iterator<String> fruitIterator;

    @SuppressWarnings("unchecked")
    @Before
    public void setUp() {
        fruitIterator = mock(Iterator.class);
        when(fruitIterator.hasNext()).thenReturn(true, true, true, false);
            when(fruitIterator.next()).thenReturn("Apple")
            .thenReturn("Banana").thenReturn("Pear");

        fruits = mock(Collection.class);
        when(fruits.iterator()).thenReturn(fruitIterator);
    }

    @Test
    public void test() {
        int iterations = 0;
        for (String fruit : fruits) {
            iterations++;
        }
        assertEquals(3, iterations);
    }
}
5 голосов
/ 17 июня 2011

Если я что-то упустил, вы, вероятно, должны возвращать реальный список проверенных значений. В этом случае создайте свой список тестовой строки в методе генератора и просто верните его. В более сложных случаях вы можете заменить содержимое списка фиктивными объектами.

Как заключительная точка, я не могу себе представить, почему вам действительно нужно было бы смоделировать расширенный цикл for. Характер модульных тестов не подходит для такого уровня проверки. Тем не менее, это интересный вопрос.

2 голосов
/ 24 июня 2016

Просто хочу указать на что-то, потому что я боролся с этим весь день:

Если вы хотите использовать синтаксис myList.forEach(...) вместо for(:), вы должны включить (где вы устанавливали свойпроверенный список):

doCallRealMethod().when(myMockedList).forEach(anyObject());
1 голос
/ 27 июня 2016

Вы хотите сделать что-то подобное.

/**
    * THe mock you want to make iterable
    */
   @Mock
   javax.inject.Instance<Integer> myMockedInstanceObject;

   /**
     * Setup the myMockedInstanceObject mock to be iterable when the business logic
     * wants to loop existing instances of the on the iterable....
     */
    private void setupTransportOrderToTransportEquipmentMapperInstancesToBeIteratble() {
        // (a) create a very real iterator object
        final Iterator<Integer> iterator = Arrays
                .asList(Integer.valueOf(1), Integer.valueOf(2)).iterator();

        // (b) make sure your mock when looped over returns a proper iterator       
        Mockito.doAnswer(new Answer<Iterator<Integer>>() {
            @Override
            public Iterator<Integer> answer(InvocationOnMock invocation)
                    throws Throwable {
                return iterator;
            }
        }).when(myMockedInstanceObject).iterator();

    }

Строковые комментарии и javadoc должны прояснить, как имитировать поведение любого итерируемого, независимо от того, является ли он списком, коллекцией javax.inject.instance или чем-то еще.

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