java Spy doReturn不改变返回值

jxct1oxe  于 2023-01-29  发布在  Java
关注(0)|答案(2)|浏览(151)

我想测试calculateApiTokenExpireDate()方法。我为currentDateTime()创建了一个spy,这样它就可以返回静态日期。但是它仍然返回当前日期。有人能告诉我哪里出错了吗?谢谢

public class ServiceHelper {

    static final long DEFAULT_OUTDATED_TIME_MILLIS = 86400000;
    static final String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm";

    long oneTimeOutDatedMillis = DEFAULT_OUTDATED_TIME_MILLIS;

    protected String getApiTokenExpireDate(){
        DateTimeFormatter customFormat = DateTimeFormatter.ofPattern(DATE_TIME_PATTERN);
        LocalDateTime tokenExpireDate = calculateApiTokenExpireDate();
        return tokenExpireDate.format(customFormat);
    }

    protected LocalDateTime calculateApiTokenExpireDate(){
        LocalDateTime now = currentDateTime();
        return now.plus(oneTimeOutDatedMillis, ChronoUnit.MILLIS);
    }

    protected LocalDateTime currentDateTime() {
        return LocalDateTime.now();
    }
}
public class ServiceHelperTest {

    private ServiceHelper serviceToTest;

    private ServiceHelper spy;

    @BeforeEach
    void beforeEach() {
        serviceToTest = new ServiceHelper();
        serviceToTest.oneTimeOutDatedMillis = 86400000;
        spy = Mockito.spy(serviceToTest);
    }

    @Test
    void calculateApiTokenExpireDate_return_plus_one_day_date() {
        /* prepare */
        doReturn(LocalDateTime.of(2023, 1, 24, 14, 1)).when(spy).currentDateTime();

        /* execute */
        LocalDateTime tokenExpireDate = serviceToTest.calculateApiTokenExpireDate();

        /* test */
        assertEquals(2023, tokenExpireDate.getYear());
        assertEquals(1, tokenExpireDate.getMonthValue());
        assertEquals(25, tokenExpireDate.getDayOfMonth());
    }
}
krcsximq

krcsximq1#

无法探查对this的调用,因为this引用未更改。您可以将类更改为在java.time.Clock示例中或在返回当前日期/时间的函数/接口上接受。然后,您可以在测试中注入Clock#fixed()
类别:

public class ServiceHelper {

    static final long DEFAULT_OUTDATED_TIME_MILLIS = 86400000;
    static final String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm";

    private final Clock clock;

    long oneTimeOutDatedMillis = DEFAULT_OUTDATED_TIME_MILLIS;

    public ServiceHelper(final Clock clock) {
        this.clock = clock;
    }

    // ...

    protected LocalDateTime calculateApiTokenExpireDate(){
        LocalDateTime now = currentDateTime();
        return now.plus(oneTimeOutDatedMillis, ChronoUnit.MILLIS);
    }

    protected LocalDateTime currentDateTime() {
        return LocalDateTime.now(clock);
    }
}

试验:

public class ServiceHelperTest {
    private ServiceHelper serviceToTest;
    private Instant now;

    @BeforeEach
    void beforeEach() {
        /* prepare */
        now = Instant.now(); // or: Instant.parse("...")
        serviceToTest = new ServiceHelper(Clock.fixed(now, ZoneOffset.UTC));
        serviceToTest.oneTimeOutDatedMillis = 86400000;

    }

    @Test
    void calculateApiTokenExpireDate_return_plus_one_day_date() {
        /* execute */
        LocalDateTime tokenExpireDate = serviceToTest.calculateApiTokenExpireDate();

        /* test */
        // assert against this.now ...
    }
}
qyuhtwio

qyuhtwio2#

看起来您模拟了类的错误示例。在测试用例中,您模拟的是ServiceHelper类的spy示例,但您调用的是serviceToTest示例上的方法,该示例是原始的“未模拟”对象。要解决此问题,您应该调用spy示例上的方法,如下所示:

LocalDateTime tokenExpireDate = spy.calculateApiTokenExpireDate();

另外,我建议您从官方文档中阅读这一节,其中有相当好的示例。

相关问题