Макет класса в тестируемом классе


Как я могу издеваться с другими классами в моем классе, который находится под тестом?

Например:

Микласс.java

class MyClass {
    public boolean performAnything() {
        AnythingPerformerClass clazz = new AnythingPerformerClass();
        return clazz.doSomething();        
    }
}

AnythingPerformerClass.java

class AnythingPerformerClass {
    public boolean doSomething() {
        //very very complex logic
        return result;
    }
}

И тест:

@Test
public void testPerformAnything() throws Exception {
    MyClass clazz = new MyClass();
    Assert.assertTrue(clazz.performAnything());
}

Могу ли я подделать AnythingPerformerClass для исключения ненужной логики из AnythingPerformerClass? Могу ли я переопределить метод doSomething() для простого возврата true или false?

Почему я указываю Mockito, потому что он мне нужен для тестирования Android с Robolectric.

3 12

3 ответа:

Вы можете рефакторировать MyClass так, чтобы он использовал инъекцию зависимостей. Вместо того, чтобы создавать экземпляр AnythingPerformerClass, Вы можете передать экземпляр класса конструктору MyClass следующим образом:

class MyClass {

   private final AnythingPerformerClass clazz;

   MyClass(AnythingPerformerClass clazz) {
      this.clazz = clazz;
   }

   public boolean performAnything() {         
     return clazz.doSomething();        
   }
}

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

@Test
public void testPerformAnything() throws Exception {
   AnythingPerformerClass mockedPerformer = Mockito.mock(AnythingPerformerClass.class);
   MyClass clazz = new MyClass(mockedPerformer);
   ...
}

Альтернативно, если ваш AnythingPerformerClass содержит состояние, то вы можете передать AnythingPerformerClassBuilder конструктору.

Как это в настоящее время (как объявление, так и создание экземпляра AnythingPerformerClass внутри метода, невозможно издеваться над AnythingPerformerClass, используя только Mockito.

Если возможно, переместите объявление и создание экземпляра AnythingPerformerClass на уровень класса: объявите переменную экземпляра типа AnythingPerformerClass и создайте ее экземпляр конструктором.

Таким образом, вы могли бы более легко ввести Макет AnythingPerformerClass во время теста и указать его поведение. Например:

when(anythingPerformerClassMock.doSomething()).thenReturn(true);

Или проверить ошибку обработка:

when(anythingPerformerClassMock.doSomething()).thenTrow(new NullPointerException());

Вы можете установить, что возвращать в Mockito.

when(mock.method()).thenReturn(someValue)