My question is similar to this one.
Setting:
I have a GreetingResource
which has a Autowired
GreetingService
to handle GET
requests:
@Path("greetings")
public class GreetingResource
{
@Autowired
private GreetingService service;
@GET
@Produces(MediaType.TEXT_PLAIN_VALUE)
public String getHello()
{
try
{
return service.greet("world");
}
catch(SQLException e)
{
System.out.println("Request failed (500)");
e.printStackTrace();
return null;
}
}
}
Problem: In my unit test I get org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type 'demo.rest.jersey.spring.GreetingService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1466)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1097)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1059)
at org.glassfish.jersey.server.spring.AutowiredInjectResolver.getBeanFromSpringContext(AutowiredInjectResolver.java:104)
at org.glassfish.jersey.server.spring.AutowiredInjectResolver.resolve(AutowiredInjectResolver.java:96)
Unit test class: In order to unit test this I have a testContext.xml
which acts as application context for unit tests. It creates just one bean, namely the TestConfig
:
@Configuration
public class TestConfig
{
@Bean
@Primary
public GreetingService greetingService() throws SQLException
{
GreetingService service = Mockito.mock(GreetingService.class);
when(service.greet(anyString())).thenReturn("Hello");
return service;
}
}
The testContext.xml
should be loaded by the unit test and hence the correct beans created:
public class Test_GreetingResource extends JerseyTest
{
@Override
protected TestContainerFactory getTestContainerFactory()
{
return new GrizzlyWebTestContainerFactory();
}
@Override
protected DeploymentContext configureDeployment(){
return ServletDeploymentContext
.forServlet(new ServletContainer(new TestApp()))
.addListener(ContextLoaderListener.class)
.contextParam("contextConfigLocation", "classpath:testContext.xml")
.build();
}
@Test
public void doTest() throws SQLException
{
String response = target("greetings").request().get(String.class);
assertEquals("response incorrect", "Hello", response);
System.out.println(response);
}
}
Notes: The TestApp
simply registers the GreetingResource
public class TestApp extends ResourceConfig
{
public TestApp()
{
register(GreetingResource.class);
packages("demo.rest.jersey.spring");
}
}
Here is also the testContext.xml
that I mentioned above:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="testConfig" class="demo.rest.jersey.spring.TestConfig"></bean>
</beans>
Additional question: If the GreetingService
mock is created as a bean, can I somehow alter the mock behaviour? I.e. right now I specify in the TestConfig
what response the mock should give but I might want to alter that behaviour from test to test.
Thanks for the help!