Подтвердить что ты не робот

Использование Mockito для подделки локальной переменной метода

У меня есть класс A, который должен быть протестирован. Ниже приведено определение A:

public class A {
    public void methodOne(int argument) {
        //some operations
        methodTwo(int argument);
        //some operations
    }

    private void methodTwo(int argument) {
        DateTime dateTime = new DateTime();
        //use dateTime to perform some operations
    }
}

И на основе значения dateTime некоторые данные должны обрабатываться, извлекаемые из базы данных. Для этой базы данных значения сохраняются через файл JSON.

Это усложняет ситуацию. Мне нужно установить dateTime на определенную дату во время тестирования. Есть ли способ, которым я могу издеваться над значением локальной переменной с помощью mockito?

4b9b3361

Ответ 1

Вы не можете издеваться над локальной переменной. Однако вы можете извлечь его создание в метод protected и spy it:

public class A {
  public void methodOne(int argument) {
    //some operations
    methodTwo(int argument);
    //some operations
  }

  private void methodTwo(int argument) {
    DateTime dateTime = createDateTime();
    //use dateTime to perform some operations
  }

  protected DateTime createDateTime() {
    return new DateTime();
  }
}

public class ATest {
  @Test
  public void testMethodOne() {
    DateTime dt = new DateTime (/* some known parameters... */);
    A a = Mockito.spy(new A());
    doReturn(dt).when(a).createDateTime();
    int arg = 0; // Or some meaningful value...
    a.methodOne(arg);
    // assert the result
}

Ответ 2

Лучший способ справиться с такой проблемой - использовать внедренную службу Clock, используемую для получения новых экземпляров DateTime. Таким образом, ваш тест может вводить mock Clock, который возвращает конкретное DateTime вместо текущего времени.

Обратите внимание, что новый API-интерфейс Java 8 определяет такой Clock class, специально для этой цели.

Ответ 3

Извините за поздний ответ.

Это может быть слишком хлопотно, но если вы смоделируете объект, который может дать вам локальную переменную, вы можете вернуть его. Я бы предпочел не реструктурировать код, чтобы облегчить тестирование, но это нужно учитывать.

public class A {

    DateTimeFactory factory;

    private void method() {
        DateTime dateTime = factory.getDateTime();
        //use dateTime to perform some operations
    }
}

В своем тесте вы можете сделать что-то вроде: when(factoryMock.getDateTime()).doReturn(dateTimeMock)

Фабричный макет нужно было бы как-то ввести в класс.