Spring Boot 使用非模拟Bean覆盖测试中的Bean

bfnvny8b  于 2023-01-13  发布在  Spring
关注(0)|答案(1)|浏览(199)

我想对一个类进行单元测试,这个类使用List的命名springbean,但是我不知道如何用我自己的充满模拟的测试bean覆盖这个bean。
定义命名Bean的类:

@Configuration
@RequiredArgsConstructor
public class JmsReceiveConfig {
    @Bean(name = "FooConsumers")
    List<JmsConsumer> messageConsumers(QueuedReceiveService fooMessageListener) throws Exception {
        List<JmsConsumer> list = new ArrayList<>();
        for (MyJmsProperties.Broker broker : myJmsProperties.getBrokers()) {
            JmsConsumer jmsConsumer =
                messageConsumer(broker, myJmsProperties.getKeystore(), myJmsProperties.getKeystorePassword(),
                    myJmsProperties.getTruststore(), myJmsProperties.getTruststorePassword(), fooMessageListener);
            list.add(jmsConsumer);
        }
        return list;
    }

    ...
}

使用命名bean的类:

@Component
@ConditionalOnEnabledHealthIndicator("barIndicator")
@RequiredArgsConstructor
public class MyHealthIndicator implements HealthIndicator {
    @Inject
    @Qualifier("FooConsumers")
    private List<JmsConsumer> jmsConsumersList;

    @Override
    public Health health() {
        int connectedCount = 0;
        Map<String, Object> detailsMap = new HashMap<>();
        for (JmsConsumer consumer : jmsConsumersList) {
            if (consumer.isConnected()) {
                connectedCount++;
            }
            detailsMap.put(consumer.getAlias(), consumer.isConnected());
        }
        return Health.up()
            .withDetails(detailsMap)
            .build();
    }
}

我试过这个测试类:

@ExtendWith(SpringExtension.class)
public class MyHealthIndicatorTest {

    private MyHealthIndicator myHealthIndicator;

    @Mock
    JmsConsumer jmsConsumer1;
    @Mock
    JmsConsumer jmsConsumer2;

    @Bean(name = "FooConsumers")
    List<JmsConsumer> messageConsumers(QueuedReceiveService fooMessageListener) throws Exception {
        ArrayList<JmsConsumer> jmsConsumers = new ArrayList<>();
        jmsConsumers.add(jmsConsumer1);
        jmsConsumers.add(jmsConsumer2);
        return jmsConsumers;
    }

    @BeforeEach
    public void setup() throws Exception {
        myHealthIndicator = new MyHealthIndicator();
    }

    @Test
    public void testStatusUpAll() {
        Mockito.when(jmsConsumer1.getAlias())
            .thenReturn("jmsConsumer1");
        Mockito.when(jmsConsumer1.isConnected())
            .thenReturn(true);
        Mockito.when(jmsConsumer2.getAlias())
            .thenReturn("jmsConsumer2");
        Mockito.when(jmsConsumer2.isConnected())
            .thenReturn(true);
        Health healthCheck = myHealthIndicator.health();
        assertEquals(healthCheck.getStatus(), Status.UP);
    }
}

我希望在myHealthIndicator.health()调用内的@Test方法中使用我在测试类中定义的命名bean,但是当该调用运行时,其中的jmsConsumer列表为空,在for (JmsConsumer consumer : jmsConsumersList)行上给出NullPointerException。
我还尝试使用一个模拟JmsReceiveConfig,以便将@BeforeEach更改为:

List<JmsConsumer> jmsConsumers = new ArrayList<>();
        jmsConsumers.add(jmsConsumer1);
        jmsConsumers.add(jmsConsumer2);
        Mockito.when(jmsReceiveConfig.messageConsumers(Mockito.any(QueuedReceiveService.class)))
            .thenReturn(jmsConsumers);
        radItsHealthIndicator = new RadItsHealthIndicator();

但是我仍然在同一个地方得到相同的NPE异常。

0pizxfdo

0pizxfdo1#

不用费心使用SpringExtension,直接使用MockitoExtension即可。
给予MyHealthIndicator一个构造函数来设置jmsConsumersList
因此setup变为:

@BeforeEach
    public void setup() throws Exception {
        ArrayList<JmsConsumer> jmsConsumers = new ArrayList<>();
        jmsConsumers.add(jmsConsumer1);
        jmsConsumers.add(jmsConsumer2);
        myHealthIndicator = new MyHealthIndicator(jmsConsumers);
    }

测试的其余部分可以保持不变(当然不需要messageConsumers())。

相关问题