如何通过单元测试测试 timeZone 方法?

我使用以下方法获取时区偏移值,例如 GMT-3,并返回给定偏移量的 time zoneId 列表。

private static List<String> getTimeZonesByZoneOffset(final int offset) {
    return ZoneId.getAvailableZoneIds()
            .stream()
            .filter(zoneId -> ZoneId.of(zoneId)
                    .getRules()
                    .getOffset(Instant.now())
                    .equals(ZoneOffset.ofHours(offset)))
            .sorted()
            .collect(Collectors.toList());
}

然后我从我的数据库中检索与我的区域列表具有相同 zoneId 的相应记录。我在我的服务中使用了这样的方法:

public List<Product> getByOffset(int offset) {
    final List<String> zones = getTimeZonesByZoneOffset(offset);
    final List<Product> products = productRepository.findAllByZone(zones);
    return getProductList(products);
}

我想在单元测试中测试这两种方法。但我不确定我应该如何设置测试机制。是否有任何单元测试示例?

回答

您的方法中有两个静态方法调用,而不是在不同的时间点返回不同的值,我建议在这两种情况下使用依赖注入来返回模拟结果。

  1. ZoneRules.getOffset(Instant)根据测试是在夏令时还是任何其他时区转换期间运行,返回不同的值。您可以通过测试固定时间来解决此问题。在标准代码和单元测试中添加依赖项Clock并将其注入。Clock.systemUTC()Clock.fixed(Instant, ZoneId)
  1. ZoneId.getAvailableZoneIds()ZoneId添加更多s时可以返回更多值。虽然ZoneRulesProvider抽象类提供了可用的区域 ID ,但没有简单的方法来禁用标准ZoneIds 并注入您自己的。如果你想通过依赖注入来解决这个问题,那么你必须创建自己的服务来返回可用的ZoneIds。

虽然ZoneRulesinZoneId可以随时间改变(例如,如果政府机构停止夏令时),它们在过去的时间是固定的,因此只要将现有的ZoneIdsInstant.now()模拟到过去的时间就没有问题.

示例代码:

import org.assertj.core.api.Assertions;
import org.junit.Test;
import java.time.Clock;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class ProductProvider {
private final Clock clock;
private final ZoneIdProvider zoneIdProvider;
public ProductProvider(Clock clock, ZoneIdProvider zoneIdProvider) {
this.clock = clock;
this.zoneIdProvider = zoneIdProvider;
}
private List<String> getTimeZonesByZoneOffset(final int offset) {
return zoneIdProvider.getAvailableZoneIds()
.stream()
.filter(zoneId -> ZoneId.of(zoneId)
.getRules()
.getOffset(clock.instant())
.equals(ZoneOffset.ofHours(offset)))
.sorted()
.collect(Collectors.toList());
}
public List<Product> getByOffset(int offset) {
final List<String> zones = getTimeZonesByZoneOffset(offset);
final List<Product> products = productRepository.findAllByZone(zones);
return getProductList(products);
}
public interface ZoneIdProvider {
Set<String> getAvailableZoneIds();
}
public static class ProductProviderTest {
@Test
public void testTimezone() {
OffsetDateTime testTime = OffsetDateTime.of(2021, 8, 26, 11, 51, 4, 0, ZoneOffset.UTC);
Clock clock = Clock.fixed(testTime.toInstant(), testTime.getOffset());
ZoneIdProvider zoneIdProvider = Mockito.mock(ZoneIdProvider.class);
Mockito.when(zoneIdProvider.getAvailableZoneIds()).thenReturn(Set.of(
ZoneId.of("America/Argentina/Buenos_Aires"), // UTC-3 year-round
ZoneId.of("America/Nuuk"), // UTC-3 as Standard Time only
ZoneId.of("America/Halifax"), // UTC-3 as Daylight Savings Time only
ZoneId.of("Europe/Paris"))); // Never UTC-3
ProductProvider productProvider = new ProductProvider(clock, zoneIdProvider);
Assertions.assertThat(productProvider.getByOffset(-3))
.isEmpty(); // Add your expected products here
}
}
}

以上是如何通过单元测试测试 timeZone 方法?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>