使用 Spring Boot 在单元测试中配置集成测试或使用 Spring JDBC?

Posted

技术标签:

【中文标题】使用 Spring Boot 在单元测试中配置集成测试或使用 Spring JDBC?【英文标题】:Configure integration test or use Spring JDBC in Unit Test using Spring Boot? 【发布时间】:2015-06-14 07:30:41 【问题描述】:

我正在使用最新版本的 Spring Boot、Spring JDBC 和 Spring Rest...

我的项目设置为一个典型的 Maven 项目,包含以下文件系统结构:

myproject
|
--src/main/java/com/myapp
--src/main/resource/application.properties
|
--src/test/java/com/myapp
--src/test/resources/application.properties
|
pom.xml

我的application.properties如下(连接本地mysql 5数据库):

spring.datasource.url=jdbc:mysql://localhost:3306/testdb
spring.datasource.username=root
spring.datasource.password=
spring.datasource.name=testdb
spring.datasource.initialize=true
spring.datasource.driverClassName=com.mysql.jdbc.Driver      

MyDAO:

public interface MyDao 

    public List<App> findAllApps(); 

MyDaoImpl:

@Repository("myDao")
public class MyDaoImpl implements MyDao 

    @Autowired 
    JdbcTemplate jdbcTemplate;

    public List<App> findAllApps() 
        List<App> apps = this.jdbcTemplate.query(
                "select app_name from app",
                new RowMapper<App>() 
                    public App mapRow(ResultSet rs, int rowNum) throws SQLException 
                        App app = new App();
                        app.setAppName(rs.getString("app_name"));
                        return app;
                    
                );

        return apps;
    

它使用依赖注入在 MyService 类中调用:

@RestController
public class MyService 

    @Autowired
    @Qualifier("myDao")
    MyDao myDao;

    @RequestMapping(value = "/apps", method = RequestMethod.GET, consumes = "text/plain", produces = "application/json")
    public void process() throws JsonParseException, IOException 
        List<App> apps = myDao.findAllApps();
        System.out.println(apps.toString());
    

这完全按照我的 RestController 中的说明工作......

但是,在典型的 JUnit 测试中:

public class MyServiceTest 

    @Autowired
    @Qualifier("myDao")
    MyDao myDao;

    @Test
    public void process() 
        List<App> apps = myDao.findAllApps();
    

对 myDao.findAllApps() 的调用返回 NullPointerException...

我什至尝试通过从命令行发出以下命令首先运行我的应用程序(使用嵌入式 tomcat):

mvn spring-boot:run 

然而,一个非数据库特定的 JUnit 测试在 Eclipse 内或当我这样做时工作:

mvn clean install

问题:

    如何设置它以便我可以运行集成测试,它实际上会从 MyServiceTest 访问我的数据库(或模拟数据库)?

    为什么尝试注入 MyServiceTest for Spring JDBC 时依赖注入失败?

    有没有办法设置我的单元测试来测试 Rest 调用?

非常感谢所有花时间阅读本文的人,非常感谢做出回应的人!

这是我的 pom.xml(根据 Eddu 的要求):

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.springframework</groupId>
    <artifactId>myproject</artifactId>
    <version>0.1.0</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.2.2.RELEASE</version>
    </parent>

    <properties>
        <java.version>1.7</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-rest-webmvc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-collections4</artifactId>
            <version>4.0</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-releases</id>
            <name>Spring Releases</name>
            <url>https://repo.spring.io/libs-release</url>
        </repository>
        <repository>
            <id>org.jboss.repository.releases</id>
            <name>JBoss Maven Release Repository</name>
            <url>https://repository.jboss.org/nexus/content/repositories/releases</url>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>spring-releases</id>
            <name>Spring Releases</name>
            <url>https://repo.spring.io/libs-release</url>
        </pluginRepository>
    </pluginRepositories>

</project>

【问题讨论】:

可以附上pom.xml吗? Eddu,我编辑了我的原始帖子,并根据您的要求附加了完整 pom.xml 文件的内容。 你在你的应用程序中使用 spring-data-jpa 吗?或者您正在将 JdbcTemplate 用于自定义存储库? Eddu,JdbcTemplate 上面列出的 MyDaoImpl... 感谢您尝试帮助我。 【参考方案1】:

您似乎没有在测试中加载 Spring 的上下文,因此没有执行依赖注入。你应该这样做:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=Application.class) //Application being your
// Spring boot base config class
public class MyServiceTest  ... 

    @Autowired
    @Qualifier("myDao")
    MyDao myDao;

您可以在我的github 中查看示例

【讨论】:

鉴于它是 Spring Boot,那么@SpringApplicationConfiguration 可能比@ContextConfiguration 更好,因此它使用SpringApplicationContextLoader WornOutSoles,感谢您的回复...为什么注入 jdbcTemplate 而不是我的 Dao? 史蒂夫,你能举个例子吗?有没有办法让服务器(或不同的服务器)在调用 JUnit 测试时运行? 考虑配置以在 spring 上下文中运行测试。此外,如果您不使用 spring-data-jpa,请通过 spring-boot-starter-jdbc 更改当前 spring-starter-data-jpa 依赖项,从而允许自动配置 JdbcTemplate。【参考方案2】:

谢谢大家!

史蒂夫 - 你是对的!

经过多次试验和磨难,@SpringApplicationConfiguration 起作用了:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes=Application.class)

Eddu Melendez - 我使用 spring-boot-starter-jdbc 删除了 spring-starter-data-jpa 依赖项,并从我的 pom.xml 文件中删除了 spring-jdbc 依赖项。

感谢大家帮助我解决这个问题!

【讨论】:

以上是关于使用 Spring Boot 在单元测试中配置集成测试或使用 Spring JDBC?的主要内容,如果未能解决你的问题,请参考以下文章

基于spring-boot的应用程序的单元+集成测试方案

[翻译]Spring Boot 中的集成测试

Spring Boot 中的单元测试

Spring Boot 集成 JUnit5,更优雅单元测试!

在 Spring Boot 中使用 Hibernate 为 DAO 层配置单元测试

带有集成测试的 Spring Boot 应用程序的 Jenkins 作业