Как смоделировать или подготовить методы тестирования, если мы вызвали закрытый метод внутри метода? - PullRequest
1 голос
/ 26 мая 2020

При написании testCase для класса Controller , закрытый метод getServiceContext (). имеет другой объект, потому что один мы передаем serviceContext из testclass , а другой объект внутри самого класса контроллера вызывает сам себя. Из-за этого объект Foo имеет значение null. как решить эту проблему.

publi c class Controller {

@Refernce
private FooService fooService;

public CustomData getDetails(String id){

      Foo foo = fooService.getFoo(id ,**getServiceContext()**); 
         //getServiceContext() is different object
    System.out.println("foo data>>>> "+foo); // **Throwing null pointer exceptions** 

      CustomData customData = new CustomData();
      customData.setStudentName(foo.getName);
      customData.setStudentName(foo.getId);
      ...
      ...
      ...
    return  customData;

}

private ServiceContext getServiceContext() {

 ServiceContext serviceContext = new ServiceContext();
    serviceContext.setCompanyId(context..);
    serviceContext.setUserId(context..);
    ...
    ....    
retrn serviceContext;

}

}


publi c class ControllerTest {

@InjectMocks
private Controller controller;

@Mock
private FooService fooService;

private Foo foo;

@BeforeEach
public void setUp() throws PortalException {

foo = mock(Foo.class);

}

@Test
public void getDetailsTest() throws Exception {

    ServiceContext **serviceContext** = new ServiceContext();
    serviceContext.setCompanyId(context..);
    serviceContext.setUserId(context..);
    ...
    ....    
    Mockito.when(fooService.getFoo("testId",serviceContext)).thenReturn(foo);

    System.out.println("Service context>>>> "+**serviceContext**); // different serviceContext object
    CustomData customData = controller.getDetails("testId");

    Assertions.assertThat(ss).isNotNull();
}

}

1 Ответ

1 голос
/ 26 мая 2020

Есть несколько способов сделать это.

Во-первых, мы можем имитировать anyOf(Type.class), который фактически будет соответствовать типу объекта, а не значению.

Mockito
 .when(fooService.getFoo(Mockit.eq("testId"), Mockito.any(ServiceContext.class)))
 .thenReturn(foo);

это будет работать как ожидаемого и верните желаемое значение.

Кроме того, если вы хотите проверить, с какими данными serviceContext объект передается как arg в методе обслуживания (поскольку мы только что проверили тип объекта, а не значение), мы можем используйте для этого ArgumentCaptor.

Он в основном захватывает данные аргумента, которые передаются при вызове метода.

давайте создадим ArgumentCaptor для контекста службы

@Mock
private FooService fooService;

@Captor
private ArgumentCaptor<ServiceContext> captor;

Теперь давайте зафиксируем аргумент во время проверки.

Mockito.verify(fooService).getFoo(Mockit.eq("testId"), captor.capture());

Assertions.assertEquals("value of x in context", captor.getValue().getX());

В основном здесь captor.getValue() возвращает объект контекста службы, который проходит. Итак, вы можете проверить все данные, которые хотите проверить в этом объекте.

Альтернативный , подход будет Spy, который будет в основном шпионить за тестируемым классом, и вы можете контролировать его поведение частных методов в самом тестовом классе.

Для этого нам нужно добавить аннотацию @Spy вместе с @InjectMocks в тестовый класс.

@Spy
@InjectMocks
private Controller controller;

Теперь вы можете издеваться над private метод и вернуть ожидаемое значение.

Mockito.doReturn(serviceContextValue).when(controller).getServiceContext();

и использовать этот объект для имитации fooService.

Mockito.verify(fooService).getFoo("testId", serviceContextValue);

Но при использовании Spy не забудьте указать unit test для частного метода, поскольку он насмехается, его бизнес-лог c не будет протестирован в приведенных выше тестовых примерах. это причина, это не рекомендуемый способ.

Я бы предложил использовать подход ArgumentCaptor.

...