Добавление фиктивного объекта в список шпионов Mockito <> - PullRequest
0 голосов
/ 16 апреля 2019

Не могу Mockito Spy Объект списка содержит другие объекты Mock, добавленные к нему? Любые альтернативы, кроме создания реальных объектов?

У меня есть объект списка шпионов

Class TestableClassTest {
@InjectMocks
TestableClass myClassUnderTest;

@Mock
MyService myService
@Spy
List<MyBusinessClass> myBusinessClasses;
@Mock 
MyBusinessClass myBusinessClass1;
@Mock
MyBusinessClass myBusinessClass2;

ResponseEntity result;

@Rule
MockitoRule rule = MockitoJunit.rule();

@Before
public void setup()
{
  myBusinessClasses.add(myBusinessClass1);
  myBusinessClasses.add(myBusinessClass2);
  when(myService.get()).thenReturn(myBusinessClasses);
  result = myClassUnderTest.testThisMethod();
}
 @Test
  public void resultIsReceivedWithNoException()
  { Assert.assertNotNull(result);}
}

Но это возвращает исключение нулевого указателя при выполнении этого

List<MyBusinessClass> list = someService.get(); MyBusinessClass 
myBusinessClass = list.get(0);// this is null

Это работает, только если я создаю настоящий Объект myBusinessClass1 и myBusinessClass2 из MyBusinessClass, а затем добавляю его в список spy(). Под этим я подразумеваю, что я больше не получаю нулевое значение, если создаю объекты с MyBusinessClass myBusinessClass1 = new MyBusinessClass(), а затем добавляю их в список.

Edit: Итак, мои вопросы, когда юнит тестирует класс, где мы возвращаем список из смоделированного метода класса 'get(). Как я могу вставить некоторые реальные конкретные данные в этот Список, чтобы мой Class Method which I am testing мог работать с этими данными, а затем я могу проверить, что мой метод работает с данными корректно.

Ответы [ 3 ]

2 голосов
/ 16 апреля 2019

Итак, мои вопросы, когда юнит тестирует класс, где мы возвращаем список из метода get () из mocked Class. Как я могу вставить некоторые реальные конкретные данные в этот список, чтобы мой метод класса, который я тестирую, мог работать с этими данными, а затем я могу проверить, что мой метод работает правильно с данными.

Учитывая, что MyBusinessClass является реальной зависимостью, обеспечивающей некоторую бизнес-логику , которая имеет свои собственные юнит-тесты, подход будет выглядеть так:

@Mock
MyService myService

List<MyBusinessClass> myBusinessClasses = new ArrayList<>();
@Mock 
MyBusinessClass myBusinessClass1;
@Mock
MyBusinessClass myBusinessClass2;

@Before
public void setup()
{
myBusinessClasses.add(myBusinessClass1);
myBusinessClasses.add(myBusinessClass2);
when(myService.get()).thenReturn(myBusinessClasses);
}

@Test
public void callSomeMethodOnReturnedEntries(){
    new CodeUnderTest(myService).publicInterfaceMethod();

    verify(myBusinessClass1).expectedMethodCall();
    verify(myBusinessClass2).expectedMethodCall();
}
1 голос
/ 16 апреля 2019

Это здесь:

@Spy
List<MyBusinessClass> myBusinessClasses;

Действительно не имеет никакого смысла.Шпион позволяет частичное издевательство над «шпионским» объектом.Таким образом, вы можете иногда вызывать «настоящие» методы и предотвращать вызов других.См. здесь , чтобы узнать, почему / как использовать шпион Mockito.

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

Таким образом, точка real такова: вы должны убедиться, как вы можете получить someService.get(); длявернуть этот список с известным содержанием.Но мы не можем помочь с этой частью, пока вы не обновите свой вопрос соответственно.

0 голосов
/ 16 апреля 2019

Моя предыдущая новость говорила, что ничто не должно быть реальным объектом

В этом случае вы также будете высмеивать (а не шпионить) коллекцию за счет необходимости указать ее простое поведение:

@Mock
MyService myService
@Mock
List<MyBusinessClass> myBusinessClasses;
@Mock 
MyBusinessClass myBusinessClass1;
@Mock
MyBusinessClass myBusinessClass2;

@Before
public void setup()
{
myBusinessClasses.add(myBusinessClass1);
myBusinessClasses.add(myBusinessClass2);

when(myBusinessClasses.size()).thenReturn(2);
when(myBusinessClasses.get(0)).thenReturn(myBusinessClass1);
when(myBusinessClasses.get(1)).thenReturn(myBusinessClass2);

when(myService.get()).thenReturn(myBusinessClasses);
}

@Test
public void callSomeMethodOnReturnedEntries(){
    new CodeUnderTest(myService).publicInterfaceMethod();

    verify(myBusinessClass1).expectedMethodCall();
    verify(myBusinessClass2).expectedMethodCall();
}

я бы для себя назвал тат перебор .

не по теме

Это будет плохой юнит-тест, так как он опирается на некоторые подробности реализации :
способ, которым ваш производственный код обращается к элементам в этом списке.

Если вы решите изменить эту подробность реализации на, скажем, используя итератор списка или API потока коллекций, вам придется изменить этот юнит-тест для принятия новой реализации.

Очень плохо, что в этом случае этот тест может не доказать, что ваш рефакторинг изменения доступа к элементу не изменил желаемого делового поведения.

...