在测试主题类中调用时,Mockbean 不会抛出错误

问题描述 投票:0回答:3

似乎返回 void 的模拟bean 在测试对象内部调用时不会抛出错误。我可以在外面调用它,但它会抛出错误。我的使用方式有问题吗?

//some imports ...
@RunWith(SpringRunner.class)
@SpringBootTest(classes={ MessagingController.class })
public class MessagingControllerTest {
    @Autowired
    private MessagingController controller;

    @MockBean
    private RabbitMessagingTemplate rabbitMessagingTemplate;

    @Test
    public void testPublishMessageConversionException() {
        //given:
        Message message = new Message(null, null, null);

        //when:
        doThrow(MessageConversionException.class).when(rabbitMessagingTemplate).convertAndSend(any());
        ResponseEntity<?> response = controller.publish(message);
        // rabbitMessagingTemplate.convertAndSend() // this throws the error
        //then:
        assertThat(response).isNotNull();
        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST);

        verify(rabbitMessagingTemplate).convertAndSend(message.getExchange(), message.getRoutingKey(), message.getPayload());
    }

 ...

}
java spring mockito spring-boot-test
3个回答
2
投票

如果你只是想进行单元测试,为什么要使用整个 spring 上下文?在我看来,SpringRunner 对于集成和 e2e 测试非常有用,但对于单元测试,您应该坚持使用 MockitoJUnitRunner。像这样的东西应该有效:

@RunWith(MockitoJUnitRunner.class)
public class MessagingControllerTest {
    @Mock
    private RabbitMessagingTemplate rabbitMessagingTemplate;

    @InjectMocks
    private MessagingController controller;

    @Test
    public void testPublishMessageConversionException() {
        //given:
        Message message = mock(Message.class);

        //when:
        when(rabbitMessagingTemplate.convertAndSend(anyObject()).thenThrow(new MessageConversionException());
        try {
            ResponseEntity<?> response = controller.publish(message);
            fail();
        } catch (MessageConversionException mce) {
            //then:
            assertThat(response).isNotNull();
            assertThat(response.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST);

            verify(rabbitMessagingTemplate, times(1)).convertAndSend(message.getExchange(), message.getRoutingKey(), message.getPayload());
        }
    }

 ...

}

0
投票

似乎那个模拟的 bean 没有被正确地存根。我必须使用特定的参数。 @Rozart还建议使用异常断言http://joel-costigliola.github.io/assertj/assertj-core-features-highlight.html#exception-assertion

这是工作中的:

@Test
    public void testPublishMessageConversionException() {
        //given:
        Message message = new Message("", "", "");

        //when:
        doThrow(MessageConversionException.class).when(rabbitMessagingTemplate).convertAndSend("","","");

        assertThatThrownBy(() -> { controller.publish(message); }).isInstanceOf(IllegalArgumentException.class)
                .hasMessageContaining("Unable to convert payload");
    }

0
投票

基于Spring文档,MockBean不能被存根:https://docs.spring.io/spring-boot/docs/2.1.18.RELEASE/reference/html/boot-features-testing.html#boot-features -测试-spring-boot-applications-mocking-beans

@MockBean 不能用于模拟 bean 的行为 在应用程序上下文刷新期间执行。到考试的时候 执行后,应用程序上下文刷新已完成,也是 迟到配置模拟行为。我们建议使用@Bean 在这种情况下创建和配置模拟的方法。

作为解决方法,我们可以使用真实的 bean 创建一个

@TestConfiguration
,如果需要,在此配置中添加依赖的
@MockBean
-s:

    @TestConfiguration
    @Import({
      MyService.class
    })
    public static class TestConfig {
       ....

    }

之后,我们可以在测试类中注入一个

@SpyBean
- 间谍将监视
@TestConfiguration
中配置的真实bean。现在我们可以使用间谍进行存根。

    @SpyBean
    private MyService myServiceSpy;


    @Test
    void myTest() {

      doThrow(NullPointerException.class)
        .when(myServiceSpy).myMethod(any());

    }
© www.soinside.com 2019 - 2024. All rights reserved.