#java #unit-testing #junit #junit4 #powermockito
Вопрос:
Я хочу, чтобы System.currentTimeMillis()
метод mock возвращал фиктивное значение при generateFileName
вызове метода из MyClassImpl
конструктора экземпляра.
...
...
public class MyClassImpl {
private String myFileName;
public MyClassImpl() {
generateFileName();
}
public String getMyFileName() {
return myFileName;
}
private void generateFileName() {
myFileName = "Request" System.currentTimeMillis();
}
}
...
...
@RunWith(PowerMockRunner.class)
@PrepareForTest(System.class)
@PowerMockIgnore({"javax.management.*"})
public class MyClassImplTest {
@Test
public void testForFileSave() throws Exception {
// Arrange
PowerMockito.mockStatic(System.class);
PowerMockito.when(System.currentTimeMillis()).thenReturn(123456789L);
System.out.println(System.currentTimeMillis() " mocked current time");
// Act
MyClassImpl myclass = new MyClassImpl();
// Assert
assertThat(myclass.getMyFileName(), is("Request" System.currentTimeMillis()));
}
}
Тестовый ответ
123456789 mocked current time
ScriptEngineManager providers.next(): javax.script.ScriptEngineFactory: Provider jdk.nashorn.api.scripting.NashornScriptEngineFactory not a subtype
INFO 2021-03-05T07:45:32,390 org.eclipse.jetty.util.log [Test worker] Logging initialized @5103ms to org.eclipse.jetty.util.log.Slf4jLog
Expected: is "Request123456789"
but: was "Request1614930331383"
Expected :Request123456789
Actual :Request1614930331383
Как устранить эту проблему?
Комментарии:
1. Что вам нужно утверждать? Являются ли эти цифры абсолютно необходимыми? Или будет достаточно, если вы проверите, что ваше имя файла != null и .содержит(«Запрос»)? Я сам много раз сталкивался с одной и той же проблемой со временем/датами, и никогда не было важно утверждать, что они были точными (в большинстве случаев до/после проверок было достаточно). Кроме того, если система выходит из строя, ничего не работает. Поэтому я действительно переосмыслил бы ценность такого утверждения
Ответ №1:
Поместите System.currentTimeMillis()
в отдельный защищенный метод. В тесте создайте тестовый класс, который расширяет MyClassImpl
и переопределяет защищенный метод, возвращая все, что вы хотите для теста.
public class MyClassImpl {
// ...
private void generateFileName() {
myFileName = "Request" currentTimeMillis();
}
protected long currentTimeMillis() {
return System.currentTimeMillis();
}
}
public class MyClassMock extends MyClassImpl {
@Override
protected long currentTimeMillis() {
return 123456789L;
}
}
Вместо использования этого пользовательского класса-макета вы также можете использовать частичные насмешки (т. Е. шпиона в mockito).