Чтобы проверить имя файла из теста, как получить издевательское значение из System.currentTimeMillis (), которое вызывается из метода экземпляра класса

#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).