Java 要验证测试中的文件名,请了解如何从类实例的方法调用的System.currentTimeMillis()中获取模拟值

Java 要验证测试中的文件名,请了解如何从类实例的方法调用的System.currentTimeMillis()中获取模拟值,java,unit-testing,junit,junit4,powermockito,Java,Unit Testing,Junit,Junit4,Powermockito,我想模拟System.currentTimeMillis()方法,以便在从MyClassImpl实例构造函数调用generateFileName方法时返回模拟值。 ... ... public class MyClassImpl { private String myFileName; public MyClassImpl() { generateFileName(); } public String getMyFileName() {

我想模拟
System.currentTimeMillis()
方法,以便在从
MyClassImpl
实例构造函数调用
generateFileName
方法时返回模拟值。

...
...

public class MyClassImpl {
    private String myFileName;

    public MyClassImpl() {
        generateFileName();
    }

    public String getMyFileName() {
        return myFileName;
    }

    private void generateFileName() {
        myFileName = "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

如何解决此问题?

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;
    }
}

除了使用这个定制的mock类,您还可以使用部分mock(即mockito中的间谍)。

您需要断言什么?这些数字是绝对必要的吗?或者如果您检查您的文件名就足够了!=null和.contains(“请求”)?我自己在时间/日期方面也遇到过很多次同样的问题,因此断言时间/日期是否准确从来都不重要(检查之前/之后的大多数时间都足够了)。此外,如果系统出现故障,则无法正常工作。所以我真的会重新思考这种断言的价值
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;
    }
}