模拟 java.time.format.DateTimeFormatter class
Mock java.time.format.DateTimeFormatter class
我正在尝试模拟 DateTimeFormatter class。我已完成以下操作:
@RunWith(PowerMockRunner.class)
@PrepareForTest({DateTimeFormatter.class})
public class UnitTest {
private DateTimeFormatter mockDateFormatter;
private AwesomeClass awesomeClass;
@Before
public void setUp() {
mockDateFormatter = PowerMockito.mock(DateTimeFormatter.class);
awesomeClass = new AwesomeClass(mockDateFormatter);
}
@Test
public void shouldToTestSomethingAwesome() {
// Other test code
PowerMockito.when(mockDateFormatter.format(any(LocalDate.class)))
.thenReturn("20150224");
// Other test code
}
AwesomeClass
用它来格式化 LocalDateTime.now(ZoneId.of("UTC"));
。格式化的字符串然后进一步用于生成另一个字符串。我需要确保正确生成字符串。所以我需要 return 来自格式化程序或模拟 LocalDateTime.now(..) 静态方法
的一致日期
我做错了什么?
模拟 LocalDateTime.now()
的另一种方法是将时钟注入您的 class 并更改您的(或添加另一个)构造函数,如下所示:
AwesomeClass(DateTimeFormatter fmt, Clock clock) {
//instead of LocalDateTime now = LocalDateTime.now():
LocalDateTime now = LocalDateTime.now(clock);
}
那么在你的测试中:
new AwesomeClass(formatter, Clock.fixed(the time you want here));
在 mockito wiki 上:Don't mock types you don't own !
This is not a hard line, but crossing this line may have repercussions! (it most likely will.)
- Imagine code that mocks a third party lib. After a particular upgrade of a third library, the logic might change a bit, but the test suite will execute just fine, because it's mocked. So later on, thinking everything is good to go, the build-wall is green after all, the software is deployed and... Boom
- It may be a sign that the current design is not decoupled enough from this third party library.
- Also another issue is that the third party lib might be complex and require a lot of mocks to even work properly. That leads to overly specified tests and complex fixtures, which in itself compromises the compact and readable goal. Or to tests which do not cover the code enough, because of the complexity to mock the external system.
Instead, the most common way is to create wrappers around the external lib/system, though one should be aware of the risk of abstraction leakage, where too much low level API, concepts or exceptions, goes beyond the boundary of the wrapper. In order to verify integration with the third party library, write integration tests, and make them as compact and readable as possible as well.
你没有控制权的 Mock 类型可以被认为是一个 (mocking) 反模式。虽然 DataTimeFormatter
几乎是 标准 ,但不应认为在即将发布的 JDK 版本中不会有任何行为变化(这在其他部分已经发生过多次在 API 中,只需查看 JDK 发行说明)。
我的观点是,如果代码需要模拟一个我不拥有的类型,设计应该改变 尽快 这样我、我的同事或此代码的未来维护者就赢了'落入这些陷阱。
Wiki 还链接到其他博客条目,描述了他们在尝试模拟他们无法控制的类型时遇到的问题。
我正在尝试模拟 DateTimeFormatter class。我已完成以下操作:
@RunWith(PowerMockRunner.class)
@PrepareForTest({DateTimeFormatter.class})
public class UnitTest {
private DateTimeFormatter mockDateFormatter;
private AwesomeClass awesomeClass;
@Before
public void setUp() {
mockDateFormatter = PowerMockito.mock(DateTimeFormatter.class);
awesomeClass = new AwesomeClass(mockDateFormatter);
}
@Test
public void shouldToTestSomethingAwesome() {
// Other test code
PowerMockito.when(mockDateFormatter.format(any(LocalDate.class)))
.thenReturn("20150224");
// Other test code
}
AwesomeClass
用它来格式化 LocalDateTime.now(ZoneId.of("UTC"));
。格式化的字符串然后进一步用于生成另一个字符串。我需要确保正确生成字符串。所以我需要 return 来自格式化程序或模拟 LocalDateTime.now(..) 静态方法
我做错了什么?
模拟 LocalDateTime.now()
的另一种方法是将时钟注入您的 class 并更改您的(或添加另一个)构造函数,如下所示:
AwesomeClass(DateTimeFormatter fmt, Clock clock) {
//instead of LocalDateTime now = LocalDateTime.now():
LocalDateTime now = LocalDateTime.now(clock);
}
那么在你的测试中:
new AwesomeClass(formatter, Clock.fixed(the time you want here));
在 mockito wiki 上:Don't mock types you don't own !
This is not a hard line, but crossing this line may have repercussions! (it most likely will.)
- Imagine code that mocks a third party lib. After a particular upgrade of a third library, the logic might change a bit, but the test suite will execute just fine, because it's mocked. So later on, thinking everything is good to go, the build-wall is green after all, the software is deployed and... Boom
- It may be a sign that the current design is not decoupled enough from this third party library.
- Also another issue is that the third party lib might be complex and require a lot of mocks to even work properly. That leads to overly specified tests and complex fixtures, which in itself compromises the compact and readable goal. Or to tests which do not cover the code enough, because of the complexity to mock the external system.
Instead, the most common way is to create wrappers around the external lib/system, though one should be aware of the risk of abstraction leakage, where too much low level API, concepts or exceptions, goes beyond the boundary of the wrapper. In order to verify integration with the third party library, write integration tests, and make them as compact and readable as possible as well.
你没有控制权的 Mock 类型可以被认为是一个 (mocking) 反模式。虽然 DataTimeFormatter
几乎是 标准 ,但不应认为在即将发布的 JDK 版本中不会有任何行为变化(这在其他部分已经发生过多次在 API 中,只需查看 JDK 发行说明)。
我的观点是,如果代码需要模拟一个我不拥有的类型,设计应该改变 尽快 这样我、我的同事或此代码的未来维护者就赢了'落入这些陷阱。
Wiki 还链接到其他博客条目,描述了他们在尝试模拟他们无法控制的类型时遇到的问题。