Мокинг двух разных реализаций интерфейса в тестовом примере контроллера Mockito Junit

У меня есть интерфейс (клиент) с двумя классами реализации PClient и SClient соответственно.

Interface  - Client
Impl class - PCleint, SClient

У меня есть контроллер, в котором оба класса impl автоматически подключены с использованием аннотации загрузки квалификатора spring. Теперь мне нужно написать тестовый пример JUNIT mockito для контроллера.

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

@Mock
private Client pclient

@Mock 
private Client sclient

Как отличить имитацию разных классов impl таким образом, чтобы вызывались методы классов impl. Должен ли я сделать, как показано ниже.

@Mock
private PClient pclient

@Mock 
private SClient sclient

У меня не получилось. Либо выдает исключение с нулевым указателем. Пожалуйста, порекомендуйте.


person Harish    schedule 12.04.2018    source источник


Ответы (1)


Я предполагаю, что хитрости в том, что вам нужно использовать Before, чтобы заглушить возвращаемое значение, и использовать @InjectMocks для контроллера. Поскольку @Mock не возвращает «настоящий» объект, он просто возвращает «фиктивный» (или фальшивый: P) объект. Поэтому, когда вы вызываете метод этого «фиктивного» объекта, он не возвращает фактический результат вашего метода, вместо этого он возвращает null. Вот почему вам нужно заглушить возврат с помощью @Before.

См. Мой пример кода ниже:

Клиентский интерфейс

public interface Client {
    String someMethod();
}

Класс реализован

public class PClient implements Client {
    private static final String name = "PClient";
    @Override
    public String someMethod() {
        return name;
    }
}


public class SClient implements Client{
    private static final String name = "SClient";
    @Override
    public String someMethod() {
        return name;
    }
}

Клиентский контроллер

@Controller общедоступный класс ClientController {

@Autowired
private PClient pClient;
@Autowired
private SClient sClient;

public ClientController(){
}
public String executePClient(){
    return this.pClient.someMethod();
}

public String executeSClient(){
    return this.sClient.someMethod();
}

public String execute(Client client){
    return client.someMethod();
}

}

Тестовый пример Вам нужно добавить @Before, чтобы заглушить возврат метода.

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

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

@RunWith(MockitoJUnitRunner.class)
public class ClientControllerTest {
    @Mock
    private PClient pclient;
    @Mock
    private SClient sclient;
    @InjectMocks
    private ClientController clientController;

    @Before
    public void setup(){
        when(pclient.someMethod()).thenReturn(new PClient().someMethod());
        when(sclient.someMethod()).thenReturn(new SClient().someMethod());
    }

    @Test
    public void testPClient(){
        String result = clientController.executePClient();
        assertEquals("PClient",result);
    }

    @Test
    public void testSClient(){
        String result = clientController.executeSClient();
        assertEquals("SClient",result);
    }

    @Test
    public void testExecuteWithPClient(){
        String result = clientController.execute(pclient);
        assertEquals("PClient",result);
    }

    @Test
    public void testExecuteWithSClient(){
        String result = clientController.execute(sclient);
        assertEquals("SClient",result);
    }
}

Результат: Пройдено тестов: 4 из 4 тестов - 31 мс

person R.yan    schedule 12.04.2018
comment
У меня вопрос. Я использую метод инициализации, могу ли я вставить его в него вместо настройки - person Harish; 12.04.2018
comment
Вы имеете в виду передать клиента в конструктор, а затем протестировать его? - person R.yan; 13.04.2018