Skip to main content
 首页 » 编程设计

java之JerseyTest如何使用SpringBoot的上下文进行测试

2023年09月08日34java哥

我的 SpringBoot@Component@Resource em> 申请。 我有正确的 JDBC 数据源,还有一些 REST 服务,由 Jersey 提供。 我想测试其中一项服务,但它会失败,它说:

Injection of autowired dependencies failed

但它不使用任何组件。

这是一个测试数据库的简单测试,它正在运行:

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = MyApplication.class) 
public class CommonRepositoryTest { 
 
    @Autowired 
    private MyRepository myRepository; 
 
    @Test 
    public void testDatabaseChangeLogsSize() { 
        int resultSize = myRepository.getTableRowSize(MyTable.TABLE_NAME); 
        System.out.println("MyTable result list size: "+resultSize); 
        assertTrue("MyTable table should has at least one row!", resultSize>0); 
    } 
 
} 

但是这个 REST 测试器不工作:

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = MyApplication.class) 
public class SampleResourceTest extends JerseyTest { 
 
    @Override 
    protected Application configure() { 
        ApplicationContext context = new AnnotationConfigApplicationContext(MyApplication.class); 
        return new ResourceConfig(SampleResource.class).property("contextConfig", context); 
    } 
 
    @Test 
    public void testSampleGet() throws Exception { 
        long id = 1; 
        String name = "name"; 
        SampleDomainModel sampleDomainModel = new SampleDomainModel(); 
        sampleDomainModel.setId(id); 
        sampleDomainModel.setName(name); 
        Response response = target("/sampleresource/samplepath/" + id).queryParam(name).request().get(Response.class); 
        SampleDomainModel responseSampleDomainModel = response.readEntity(SampleDomainModel.class); 
        assertEquals(sampleDomainModel.getId(), responseSampleDomainModel.getId()); 
    } 
 
} 

如您所见,它必须覆盖 JerseyTest 中的 configure() 方法。 我认为问题在于,AnnotationConfigApplicationContext 可能无法加载任何内容(?)。 @SpringApplicationConfiguration(classes = MyApplication.class) 注释加载了上下文,但是 new AnnotationConfigApplicationContext(MyApplication.class) 代码可能会失败,它没有完整的上下文。

如果我用模拟替换代码,它就可以工作(但这不是一个好方法):

@Override 
protected Application configure() { 
    ApplicationContext mockContext = Mockito.mock(ApplicationContext.class); 
    return new ResourceConfig(SampleResource.class).property("contextConfig", mockContext); 
} 

失败信息是:

2016-05-13 13:25:39.617  WARN 9832 --- [           main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myRepositoryImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.jdbc.core.JdbcTemplate com.repository.impl.myRepositoryImpl.jdbcTemplate; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$JdbcTemplateConfiguration': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private javax.sql.DataSource org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$JdbcTemplateConfiguration.dataSource; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration$NonEmbeddedConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.sql.DataSource]: Factory method 'dataSource' threw exception; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Cannot determine embedded database driver class for database type NONE. If you want an embedded database please put a supported one on the classpath. If you have database settings to be loaded from a particular profile you may need to active it (no profiles are currently active). 
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.422 sec <<< FAILURE! - in com.ws.server.SampleResourceTest 
testSampleGetWithCorrectParameters(com.ws.server.SampleResourceTest)  Time elapsed: 0.015 sec  <<< ERROR! 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myRepositoryImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.jdbc.core.JdbcTemplate com.repository.impl.MyRepositoryImpl.jdbcTemplate; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$JdbcTemplateConfiguration': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private javax.sql.DataSource org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$JdbcTemplateConfiguration.dataSource; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration$NonEmbeddedConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.sql.DataSource]: Factory method 'dataSource' threw exception; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Cannot determine embedded database driver class for database type NONE. If you want an embedded database please put a supported one on the classpath. If you have database settings to be loaded from a particular profile you may need to active it (no profiles are currently active). 
    at org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.getDriverClassName(DataSourceProperties.java:180) 
    at org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$NonEmbeddedConfiguration.dataSource(DataSourceAutoConfiguration.java:121) 

本次 Jersey 测试如何使用SpringBoot上下文?

请您参考如下方法:

简而言之,您不能同时使用 Spring 的 TestContext 和 Jersey 测试框架。它们将在两个不同的 ApplicationContext 上运行。即使您尝试将 ApplicationContext(创建为 TestContext)注入(inject)测试类并将其传递给 configure 方法中的 ResourceConfig,为时已晚,因为注入(inject)直到 构造之后才发生,但是 `configure 方法 构造期间被调用。

忘记 JerseyTest 并只使用 @WebIntegrationTest .参见 the sample来自 spring boot 项目。

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(SampleJerseyApplication.class) 
@WebIntegrationTest(randomPort = true) 
public class SampleJerseyApplicationTests { 
 
    @Value("${local.server.port}") 
    private int port; 

在 Jersey/Boot 环境中,Jersey 需要在 Web 应用程序环境中运行,这就是 @WebIntegrationTest 所做的。

对于客户端,您只需要创建客户端,而不仅仅是在 JerseyTest 上调用 target

Client client = ClientBuilder.newClient(); 
WebTarget target = client.target("http://localhost:" + this.port); 
 
Response response = target.path("/sampleresource/samplepath/" + id).request().get();