如何在Spring测试中连接依赖项

时间:2018-03-14 10:31:57

标签: java spring mocking mockito

我很难弄清楚如何在Spring中编写单元测试。

这是我尝试测试的方法:

@Service
public class ActionRequestHandler {

    @Autowired
    private Vertx vertx;

    @Autowired
    private InventoryService inventoryService;

    @Autowired
    private RequestSerializationWrapper requestWrapper;

    @Autowired
    private ProducerTemplate producer;

    @EventListener
    @Transactional
    public void registerConsumer(ApplicationReadyEvent event) {
        EventBus eb = vertx.eventBus();

        eb.consumer("bos.admin.wui.action", (Message<String> msg) -> {
            handleIncomingRequest(msg);
        });
    }
    // ...
}

到目前为止,我已经尝试在我的测试类中创建一个配置,如下所示:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
public class ActionRequestHandlerTest {

    @Configuration
    static class ContextConfiguration {

        @Bean
        @Primary
        public Vertx vertx() {
            return Mockito.mock(Vertx.class);
        }

        @Bean
        @Primary
        public InventoryService inventoryService() {
            return Mockito.mock(InventoryService.class);
        }

        @Bean
        @Primary
        public RequestSerializationWrapper requestWrapper() {
            return new RequestSerializationWrapper();
        }
    }

    @Autowired
    private Vertx vertx;

    @Autowired
    private InventoryService inventoryService;

    @Autowired
    private RequestSerializationWrapper requestWrapper;

    @Autowired
    private ActionRequestHandler systemUnderTest;

    @Test
    public void registerConsumer_shouldRegisterVertxEventBusConsumer() {
        EventBus eventBusMock = Mockito.mock(EventBus.class);
        Mockito.when(vertx.eventBus()).thenReturn(eventBusMock);

        systemUnderTest.registerConsumer(null);

        Mockito.verify(eventBusMock.consumer(Matchers.anyString()), Mockito.times(1));
    }
}

然而,这似乎试图解决InventoryService中的每个依赖,而不是模拟整个类。上面的配置在运行时给出了这个错误:

Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private admin.messaging.converters.XmlToEntityConverter admin.persistence.service.InventoryService.entityConverter; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [admin.messaging.converters.XmlToEntityConverter] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

我还尝试使用建议here的配置文件。配置类看起来相同:

@Profile("test")
@Configuration
public class ActionRequestHandlerTestConfiguration {

    @Bean
    @Primary
    public Vertx vertx() {
        return Mockito.mock(Vertx.class);
    }

    @Bean
    @Primary
    public InventoryService inventoryService() {
        return Mockito.mock(InventoryService.class);
    }

    @Bean
    @Primary
    public RequestSerializationWrapper requestWrapper() {
        return new RequestSerializationWrapper();
    }
}

测试的设置略有不同,而是使用以下注释:

@ActiveProfiles("test")
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = ActionRequestHandler.class)
public class ActionRequestHandlerTest {
    // ...
}

但是这反过来给我一个错误,Vertx无法接线:

Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private io.vertx.core.Vertx admin.messaging.request.ActionRequestHandler.vertx; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [io.vertx.core.Vertx] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

我怎样才能让它发挥作用?我哪里错了?

2 个答案:

答案 0 :(得分:1)

您不需要整个Spring语境来为ActionRequestHandler编写单元测试。您应该使用MockitoJunitRunner代替并对依赖项进行模拟。

@RunWith(MockitoJunitRunner.class)
public class ActionRequestHandlerTest {

    @Mock
    private Vertx vertx;

    @Mock
    private InventoryService inventoryService;

    @Mock
    private RequestSerializationWrapper requestWrapper;

    @Mock
    private ProducerTemplate producer;

    @InjectMocks
    private ActionRequestHandler actionRequestHandler;

    @Test
    public void testRegisterConsumer() {
      .... Your code to test ActionRequestHandler#registerConsumer will go here....
    }
}

您可以详细了解here

答案 1 :(得分:0)

尝试

@ContextConfiguration("/test-context.xml")
@RunWith(SpringJUnit4ClassRunner.class)

这告诉Junit在测试的同一目录中使用test-context.xml文件。这个文件应该类似于你在春天使用的真正的context.xml,但是自然地指向测试资源。