简体   繁体   English

使用 static 方法初始化的私有字段的单元测试方法

[英]Unit testing method which is using a private field initialized with static method

In my class TwitchService I'm creating a private field twitchClient using TwitchClientBuilder .在我的 class TwitchService ,我使用TwitchClientBuilder twitchClient How can I approach testing method sendChatMessage() which is using 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);
    }
}

So far, I have tried mocking TwitchClientBuilder.builder() and twitchCliendBuilder.build() like this:到目前为止,我已经像这样尝试了 mocking 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");
        }

    }
}

But I get NullPointerException on twitchClient in sendChatMessage() Any ideas how to properly mock fields like this?但是我在sendChatMessage()twitchClient上得到NullPointerException任何想法如何正确模拟这样的字段?

Use constructor dependency injection for TwitchClient , instead of hard-coding it by calling builder.TwitchClient使用构造函数依赖注入,而不是通过调用 builder 对其进行硬编码。

Simply re-write your service, like so:只需重新编写您的服务,就像这样:

public class TwitchService {

    private final TwitchClient twitchClient

    public TwitchService(final TwitchClient twitchClient) {
        this.twitchClient = twitchClient;
    }

...
}

TwitchService is now loosely-coupled with the implementation of TwitchClient , which gives you ability to mock the client in the unit tests and use real-implementation (unit tested by itself) in real-code. TwitchService现在与TwitchClient的实现松散耦合,这使您能够在单元测试中模拟客户端并在实际代码中使用实际实现(单元测试本身)。

So in unit-test, we can mock 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(...);
        ...
    }

and in the real code, we "inject" real TwitchClient built by TwitchClientBuilder :在真实代码中,我们“注入”了由TwitchClient构建的真实TwitchClientBuilder

...
twitchService = new TwitchService(TwitchClientBuilder.builder().build());
...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM