测试场景:

mockito如何测方法入参中的匿名内部类

假设要测试如下的一段业务代码

@Service
public class MyServiceImpl {

    /**
     * 消息服务
     */
    @Resource
    private MessageService messageService;

    public boolean save(SysUser sysUser) {
        //保存用户(省略代码)
        Message message = new Message();
        message.setContent(String.format("用户信息保存成功[%d]", sysUser.getId()));
        //调用消息服务发送消息
        messageService.send(message, baseResponse -> {
            if (baseResponse.getCode() == 0) {
                System.out.println("消息发送成功了");
            }
        });
        return true;
    }
}

代码解释:保存用户的一段逻辑代码,当用户保存之后调用消息服务发送消息,消息服务的send方法无返回值,依靠回调告知调用方消息发送状态。有两个参数第一个是消息内容,第二个是回调函数,这里用函数接口Consumer表示。


测试代码:

MessageService如何实现发送逻辑的我们不关心,只希望自己的业务代码能够被正确测试即可,这里需要对MessageService进行Mock,单元测试代码如下

@ExtendWith(MockitoExtension.class)
public class MyServiceImplTest {

    @InjectMocks
    private MyServiceImpl myService;

    @Mock
    private MessageService messageServiceStub;

    @Test
    void should_send_message_success_when_message_service_available() {
        //given
        SysUser sysUser = new SysUser();
        sysUser.setId(1);
        sysUser.setName("张三");
        ArgumentCaptor<Message> messageArgumentCaptor = ArgumentCaptor.forClass(Message.class);

        //when
        boolean result = myService.save(sysUser);

        //then
        verify(messageServiceStub, times(1)).send(messageArgumentCaptor.capture(), any());
        assertThat(messageArgumentCaptor.getValue().getContent()).isEqualTo("用户信息保存成功[1]");
        assertTrue(result);
    }
}

上面单元测试方法执行后,代码覆盖率如下
在这里插入图片描述
通过覆盖率颜色可以看到匿名内部类中的代码未被调用,因为MessageService已经被Mock。如何操作才能调用到匿名内部类中的代码,代码调整如下

    @Test
    void should_send_message_success_when_message_service_available() {
        //given
        SysUser sysUser = new SysUser();
        sysUser.setId(1);
        sysUser.setName("张三");
        ArgumentCaptor<Message> messageArgumentCaptor = ArgumentCaptor.forClass(Message.class);
        doAnswer(invocationOnMock -> {
            Consumer<BaseResponse<Object>> listener = invocationOnMock.getArgument(1);
            BaseResponse<Object> baseResponse = new BaseResponse<>();
            baseResponse.setCode(0);
            listener.accept(baseResponse);
            return null;
        }).when(messageServiceStub).send(any(), any());

        //when
        boolean result = myService.save(sysUser);

        //then
        verify(messageServiceStub, times(1)).send(messageArgumentCaptor.capture(), any());
        assertThat(messageArgumentCaptor.getValue().getContent()).isEqualTo("用户信息保存成功[1]");
        assertTrue(result);
    }

修改后的代码覆盖率如下
在这里插入图片描述


Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐