gpt4 book ai didi

java - 如何通过单元测试测试时区方法?

转载 作者:行者123 更新时间:2023-12-02 02:01:44 26 4
gpt4 key购买 nike

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

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

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

最佳答案

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

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

虽然 ZoneId 中的 ZoneRules 可以随时间变化(例如,如果政府机构停止使用夏令时),它们在过去的时间是固定的,所以只要 Instant.now() 被模拟到过去的某个时间,返回现有的 ZoneId 就没有问题。

示例代码:

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

}

关于java - 如何通过单元测试测试时区方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68938012/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com