издевательство над рекурсивным классом

#java #junit #mockito #junit5

Вопрос:

использование Spring 2.0.3.RELEASE, JUnit Jupiter 5.7.0, Mockito 3.3.3

попробуйте протестировать метод method01 класса Class01:

 public class Class01 {

 private RestConnector con;
 
 public Class01(){
  con = RestConnector.getInstance();
 }

 public Response method01(String x) {
  Class01 example = new Class01();
  String x = example.isAuthenticated();
  
  // more stuff after this
  
 }
 
 public String isAuthenticated() throws IOException {
  // I do stuff
  return "a string";
 }

}  
 

В тестовом классе пробовали

 public class Class01Test{

 @Mock private Class01 class01Mock;
 
 @Spy @InjectMocks private Class01 class01;

 @Test
 public void test() throws Throwable {
  
  doReturn("I returned").when(class01).  ??? stuck here .. always goes into the isAuthenticated method
  Response result = class01.method01("a string");
 }

}
 

В настоящее время тест всегда выполняется, реальный метод аутентифицирован.
Как настроить макет для примера поля в методе method01 так, чтобы выполнение пропусков, переходящих в метод, было аутентифицировано?

Комментарии:

1. Макет никогда не используется с тех пор method01 , как создается новый экземпляр. Но почему внутри создается новый экземпляр method01 ? Если это действительно необходимо, введите макет через конструктор или передайте в качестве параметра.

2. насколько я понимаю, это делает то, что он пытается подключиться к внешнему серверу. если это не удается, он пытается найти другое место. Не следуя тому, что вы подразумеваете под «внедрить макет через конструктор или передать в качестве параметра»

Ответ №1:

попробуйте протестировать метод method01 класса Class01

Тогда вам не нужны насмешки.

  @Test
 public void test() throws Throwable {
  Class01 c = new Class01();

  Response expected = ... ;
  assertEquals(c.method01("input"), expected);
 }
 

Если вы хотите ввести поведение в example переменную, вам нужно переместить ее в поле

 public class Class01 {

 private RestConnector con;
 private Class01 inner;
 
 public Class01(){
  con = RestConnector.getInstance();
 }

 Class01(Class01 c) {
   this();
   this.inner = c;
 }

 public Response method01(String x) {
  String x = inner.isAuthenticated();
  
  // more stuff after this
  
 }
 

Вместе с издевательством

 @RunWith(MockitoJunitRunner.class)
public class Class01Test{

 @Mock Class01 class01Mock;

 @Test
 public void test() throws Throwable {
  Response expected = ... ;
  when(class01Mock.isAuthenticated()).thenReture(expected); ... // TODO: Setup  
 
  Class01 c = new Class01(class01Mock); // pass in the mock
  
  assertEquals(c.method01("input"), expected);
 }

 

Однако неясно, зачем вам нужен вложенный объект того же класса, когда вам, по-видимому, нужен только this.isAuthenticated()

В идеале вы бы также издевались над RestConnector