Хобрук: Ваш путь к мастерству в программировании

Настроить интеграционный тест или использовать Spring JDBC в модульном тесте с помощью Spring Boot?

Я использую последние версии 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

Вопросы):

  1. Как я могу настроить его, чтобы я мог запустить интеграционный тест, и он действительно попадал в мою базу данных (или фиктивную базу данных, если на то пошло) из MyServiceTest?

  2. Почему происходит сбой внедрения зависимостей при попытке внедрения в MyServiceTest для Spring JDBC?

  3. Есть ли способ настроить мои модульные тесты для проверки вызовов Rest?

Большое спасибо всем, кто нашел время, чтобы прочитать это, и большое спасибо людям, которые откликнулись!

Вот мой pom.xml (по запросу Эдду):

<?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? 09.04.2015
  • Эдду, я отредактировал свой исходный пост и добавил содержимое полного файла pom.xml по вашему запросу. 09.04.2015
  • Вы используете spring-data-jpa в своем приложении? Или вы используете JdbcTemplate для пользовательских репозиториев? 09.04.2015
  • Eddu, JdbcTemplate указан выше в MyDaoImpl... Спасибо за попытку помочь мне. 09.04.2015

Ответы:


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

09.04.2015
  • Учитывая, что это Spring Boot, тогда @SpringApplicationConfiguration может быть лучше, чем @ContextConfiguration, так как он использует SpringApplicationContextLoader. 09.04.2015
  • WornOutSoles, Спасибо за ответ... Зачем вводить jdbcTemplate вместо моего Dao? 09.04.2015
  • Стив, можешь привести пример? Есть ли способ заставить сервер (или другой сервер) работать, когда затем вызывается тест JUnit? 09.04.2015
  • Примите во внимание конфигурацию для запуска теста в контексте весны. Более того, если вы не используете spring-data-jpa, измените текущую зависимость spring-starter-data-jpa на spring-boot-starter-jdbc, что позволит автоматически настроить JdbcTemplate. 09.04.2015

  • 2

    Спасибо всем!

    Стив - ты был прав!

    После долгих проб и невзгод @SpringApplicationConfiguration сработала:

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

    Эдду Мелендес. Я удалил зависимость spring-starter-data-jpa с помощью spring-boot-starter-jdbc, а также удалил зависимость spring-jdbc из моего файла pom.xml.

    Спасибо всем за попытку помочь мне решить эту проблему!

    09.04.2015
    Новые материалы

    Прогресс в технологии Трансформеров часть 3
    Многомасштабный управляющий сигнальный преобразователь для бесфазного синтеза движения (arXiv) Автор: Линтао Ван , Кун Ху , Лей Бай , Юй Дин , Ваньли Оуян , Чжиюн Ван . Аннотация:..

    Представляем поддержку компонентов Vue.js. Мгновенный HMR и многое другое.
    Хотя у FuseBox уже был плагин Vue, он был базовым и не имел многих функций, которые делали работу с Vue.js такой приятной. Однако с этим выпуском мы рады сообщить, что в FuseBox..

    Приключения в Javascript, часть 1
    Я продолжаю думать о том, чтобы писать больше, но чем больше я думаю об этом, тем меньше я это делаю. Итак, сегодня я перестал думать и начал писать. Отсюда можно только спускаться… В..

    Понимание дженериков в TypeScript: подробное руководство
    Введение TypeScript, строго типизированный надмножество JavaScript, хорошо известен своей способностью улучшать масштабируемость, удобочитаемость и ремонтопригодность приложений. Одной из..

    Учебные заметки JavaScript Object Oriented Labs
    Вот моя седьмая неделя обучения программированию. После ruby ​​и его фреймворка rails я начал изучать самый популярный язык интерфейса — javascript. В отличие от ruby, javascript — это более..

    Разбор строк запроса в vue.js
    Иногда вам нужно получить данные из строк запроса, в этой статье показано, как это сделать. В жизни каждого дизайнера/разработчика наступает момент, когда им необходимо беспрепятственно..

    Предсказание моей следующей любимой книги 📚 Благодаря данным Goodreads и машинному обучению 👨‍💻
    «Если вы не любите читать, значит, вы не нашли нужную книгу». - J.K. Роулинг Эта статья сильно отличается от тех, к которым вы, возможно, привыкли . Мне очень понравилось поработать над..