Использование 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?
Ответы
Ответ 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)
Фабричный макет нужно было бы как-то ввести в класс.