Reputation: 2255
I'm having a hard time figuring out how to write Unit tests in Spring.
This is the method I'm trying to test:
@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);
});
}
// ...
}
So far I have tried creating a configuration inside my test class, like this:
@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));
}
}
However, this seems to try to resolve every dependency inside InventoryService instead of mocking the entire class. The above configuration gives me this error when I run:
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)}
I have also tried using a profile as suggested here. The configuration class looks the same:
@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();
}
}
The test is set up a bit differently with the following annotations instead:
@ActiveProfiles("test")
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = ActionRequestHandler.class)
public class ActionRequestHandlerTest {
// ...
}
But this instead gives me an error that Vertx can't be wired:
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)}
How can I get this to work? Where am I going wrong?
Upvotes: 0
Views: 1134
Reputation: 4597
You don't need whole spring context to write unit test for ActionRequestHandler
. You should use MockitoJunitRunner
instead and do mocking on the dependencies.
@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....
}
}
You can read more about it here.
Upvotes: 1
Reputation: 818
Try
@ContextConfiguration("/test-context.xml")
@RunWith(SpringJUnit4ClassRunner.class)
This tells Junit to use the test-context.xml file in the same directory as your test. This file should be similar to the real context.xml you're using for spring, but pointing to test resources, naturally.
Upvotes: 0