使用静态方法初始化的私有字段的单元测试方法
Unit testing method which is using a private field initialized with static method
在我的 class TwitchService
中,我正在使用 TwitchClientBuilder
创建一个私有字段 twitchClient
。我怎样才能接近使用 twitchClient
的测试方法 sendChatMessage()
?
public class TwitchService {
public TwitchService(){
twitchClient = TwitchClientBuilder.builder().build();
}
public void sendChatMessage(String content) throws Exception {
if(content.isEmpty()){
throw new Exception("Cannot send empty message!");
}
twitchClient.getChat().sendMessage(content);
}
}
到目前为止,我试过像这样模拟 TwitchClientBuilder.builder()
和 twitchCliendBuilder.build()
:
@RunWith(MockitoJUnitRunner.class)
public class TwitchServiceTest {
private TwitchService twitchService;
@Mock
private TwitchClientBuilder twitchClientBuilder;
@Test
public void sendChatMessage() throws Exception {
try (MockedStatic<TwitchClientBuilder> twitchClientBuilderMockedStatic = Mockito.mockStatic(TwitchClientBuilder.class)){
twitchClientBuilderMockedStatic.when(() -> TwitchClientBuilder.builder()).thenReturn(mock(TwitchClientBuilder.class));
when(twitchClientBuilder.build()).thenReturn(mock(TwitchClient.class));
twitchService = new TwitchService("x", "y");
twitchService.sendChatMessage("test message");
}
}
}
但我在 sendChatMessage()
twitchClient
得到 NullPointerException
有什么想法可以正确模拟这样的字段吗?
对TwitchClient
使用构造函数依赖注入,而不是通过调用构建器对其进行硬编码。
只需重写您的服务,如下所示:
public class TwitchService {
private final TwitchClient twitchClient
public TwitchService(final TwitchClient twitchClient) {
this.twitchClient = twitchClient;
}
...
}
TwitchService
现在与 TwitchClient
的实现松散耦合,这使您能够在单元测试中模拟客户端并在实际中使用实际实现(单元测试本身) -代码。
所以在单元测试中,我们可以模拟 TwitchClient
:
@RunWith(MockitoJUnitRunner.class)
public class TwitchServiceTest {
@Mock
private TwitchClient mockedTwitchClient;
// Tested instance
private TwitchService twitchService;
@Before
public void before() {
twitchService = new TwitchService(mockedTwitchClient);
}
@Test
public void ourTest() {
when(mockedTwitchClient.xyz()).thenReturn(...);
...
}
并且在真实代码中,我们“注入”由 TwitchClientBuilder
:
构建的真实 TwitchClient
...
twitchService = new TwitchService(TwitchClientBuilder.builder().build());
...
在我的 class TwitchService
中,我正在使用 TwitchClientBuilder
创建一个私有字段 twitchClient
。我怎样才能接近使用 twitchClient
的测试方法 sendChatMessage()
?
public class TwitchService {
public TwitchService(){
twitchClient = TwitchClientBuilder.builder().build();
}
public void sendChatMessage(String content) throws Exception {
if(content.isEmpty()){
throw new Exception("Cannot send empty message!");
}
twitchClient.getChat().sendMessage(content);
}
}
到目前为止,我试过像这样模拟 TwitchClientBuilder.builder()
和 twitchCliendBuilder.build()
:
@RunWith(MockitoJUnitRunner.class)
public class TwitchServiceTest {
private TwitchService twitchService;
@Mock
private TwitchClientBuilder twitchClientBuilder;
@Test
public void sendChatMessage() throws Exception {
try (MockedStatic<TwitchClientBuilder> twitchClientBuilderMockedStatic = Mockito.mockStatic(TwitchClientBuilder.class)){
twitchClientBuilderMockedStatic.when(() -> TwitchClientBuilder.builder()).thenReturn(mock(TwitchClientBuilder.class));
when(twitchClientBuilder.build()).thenReturn(mock(TwitchClient.class));
twitchService = new TwitchService("x", "y");
twitchService.sendChatMessage("test message");
}
}
}
但我在 sendChatMessage()
twitchClient
得到 NullPointerException
有什么想法可以正确模拟这样的字段吗?
对TwitchClient
使用构造函数依赖注入,而不是通过调用构建器对其进行硬编码。
只需重写您的服务,如下所示:
public class TwitchService {
private final TwitchClient twitchClient
public TwitchService(final TwitchClient twitchClient) {
this.twitchClient = twitchClient;
}
...
}
TwitchService
现在与 TwitchClient
的实现松散耦合,这使您能够在单元测试中模拟客户端并在实际中使用实际实现(单元测试本身) -代码。
所以在单元测试中,我们可以模拟 TwitchClient
:
@RunWith(MockitoJUnitRunner.class)
public class TwitchServiceTest {
@Mock
private TwitchClient mockedTwitchClient;
// Tested instance
private TwitchService twitchService;
@Before
public void before() {
twitchService = new TwitchService(mockedTwitchClient);
}
@Test
public void ourTest() {
when(mockedTwitchClient.xyz()).thenReturn(...);
...
}
并且在真实代码中,我们“注入”由 TwitchClientBuilder
:
TwitchClient
...
twitchService = new TwitchService(TwitchClientBuilder.builder().build());
...