泽西岛 - 采用弹簧注入服务的单元测试资源

时间:2017-12-08 11:25:57

标签: java spring unit-testing jersey-2.0

我的问题类似于this one

设置 : 我有GreetingResource Autowired GreetingService来处理GET次请求:

@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;
    }
}
}

问题 :在我的单元测试中,我得到了     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)

单元测试类 :为了对单元测试进行单元测试,我有testContext.xml作为单元测试的应用程序上下文。它只创建一个bean,即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;
    }
}

testContext.xml应该由单元测试加载,因此创建了正确的bean:

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);
    }
}

备注 TestApp只是注册GreetingResource

public class TestApp extends ResourceConfig 
{
    public TestApp()
    {
        register(GreetingResource.class);
        packages("demo.rest.jersey.spring");
    }
}

以下是我上面提到的testContext.xml

<?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>

其他问题 :如果将GreetingService模拟创建为bean,我可以以某种方式改变模拟行为吗?即现在我在TestConfig中指定模拟应该给出的响应,但我可能想要改变从测试到测试的行为。

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

我关注this answer并将GreetingService注入GreetingResource的构造函数中。

然后就是

public class Test_GreetingResource extends JerseyTest
{
    @Mock
    private GreetingService service;

    @Override
    public ResourceConfig configure() 
    {
        MockitoAnnotations.initMocks(this);
        return new ResourceConfig()
            .register(new GreetingResource(service));
    }

    @Test
    public void testMockedGreetingService() 
    {
        try {
            when(service.greet(anyString())).thenReturn("Hello there");
        } catch (SQLException e) {
            fail("service cannot greet");
        }

        Response response = target("greetings")
                .request(MediaType.TEXT_PLAIN).get();

        String msg = response.readEntity(String.class);
        System.out.println("Message: " + msg);

        response.close();
    }
}