【问题标题】:Spring Boot 5 multiple JUnit JPA test files wiringSpring Boot 5 多个 JUnit JPA 测试文件接线
【发布时间】:2018-06-29 22:22:55
【问题描述】:

我在项目中有两个测试文件。 一种是直接测试我的持久层:

@RunWith(SpringRunner.class)
@DataJpaTest
public class UserTests {

    @Autowired
    private TestEntityManager entityManager;

    @Autowired
    private UserRepository repository;

    @Test
    public void whenFindByEmail_thenReturnUser() {
        // given
        User user = new User("email@email.com", "12345678", "Some Name");
        entityManager.persist(user);
        entityManager.flush();

        // when
        User found = repository.findByEmail(user.getEmail());

        // then
        assertThat(found.getName()).isEqualTo(user.getName());
        assertThat(found.getEmail()).isEqualTo(user.getEmail());
        assertThat(found.getPasswordHash()).isEqualTo(user.getPasswordHash());
    }
}

另一个是使用持久层测试服务:

@RunWith(SpringRunner.class)
@DataJpaTest
public class UserServiceTests {

    @Autowired
    private UserService service;

    @Test
    public void testSuccessfullUserCreation() {
        UserCreationResult res = service.createUser("anything@anything.com", "1234567890", "Test");
        assertThat(res).isEqualTo(UserCreationResult.OK);
    }

    @Test
    public void testWrongEmailUserCreation() {
        UserCreationResult res = service.createUser("anything@anything", "1234567890", "Test");
        assertThat(res).isEqualTo(UserCreationResult.INVALID_EMAIL);
    }

    @Test
    public void testTooShortPasswordUserCreation() {
        String shortPassword =
                String.join("", Collections.nCopies(UserService.minPasswordLength - 1, "0"));
        UserCreationResult res = service.createUser("anything@anything.com", shortPassword, "Test");
        assertThat(res).isEqualTo(UserCreationResult.WRONG_PASSWORD_LENGTH);
    }

    @Test
    public void testTooLongPasswordUserCreation() {
        String longPassword =
                String.join("", Collections.nCopies(UserService.maxPasswordLength + 1, "0"));
        UserCreationResult res = service.createUser("anything@anything.com", longPassword, "Test");
        assertThat(res).isEqualTo(UserCreationResult.WRONG_PASSWORD_LENGTH);
    }

    @Test
    public void testMaxLengthPasswordUserCreation() {
        String maxPassword =
                String.join("", Collections.nCopies(UserService.maxPasswordLength, "0"));
        UserCreationResult res = service.createUser("anything@anything.com", maxPassword, "Test");
        assertThat(res).isEqualTo(UserCreationResult.OK);
    }

    @Test
    public void testMinLengthPasswordUserCreation() {
        String minPassword =
                String.join("", Collections.nCopies(UserService.minPasswordLength, "0"));
        UserCreationResult res = service.createUser("anything@anything.com", minPassword, "Test");
        assertThat(res).isEqualTo(UserCreationResult.OK);
    }

    @Test
    public void testReservedEmailUserCreation() {
        String email = "email@email.com";
        UserCreationResult res = service.createUser(email, "1234567890", "Test");
        assertThat(res).isEqualTo(UserCreationResult.OK);
        res = service.createUser(email, "1234567890", "Test");
        assertThat(res).isEqualTo(UserCreationResult.RESERVED_EMAIL);
    }
}

首先,我的服务自动装配不起作用 (UnsatisfiedDependencyException) 所以我必须添加: @ComponentScan("my.service.package") 注释到测试类。

这使得UserServiceTests 的测试在独立运行时可以工作(使用 eclipse 只运行这个类)。

但是在运行我的应用程序的所有测试时(在 eclipse 中或使用旧的 mvn clean test),我在同一个测试类上遇到了同样的错误。

我尝试将相同的组件扫描注释添加到另一个测试类 (UserTests),然后一切正常。

我从UserServiceTests 中删除了组件扫描注释,它仍然有效。

我显然推断出测试的执行顺序很重要。

这是我的 3 个问题,真正的问题是最后一个:

  1. 首先,即使我的类被正确注释@Service(所以应该被检测为 bean),为什么我必须放置这个组件扫描注释?
  2. 测试顺序有什么关系?
  3. 如何让多个 JPA 测试文件通过适当的依赖注入独立运行?

这是我的服务类:

@Service
public class UserService {

    @Autowired
    private UserRepository repository;

    public static final int minPasswordLength = 8;
    public static final int maxPasswordLength = 50;

    public static enum UserCreationResult {
        OK, INVALID_EMAIL, RESERVED_EMAIL, WRONG_PASSWORD_LENGTH, UNKNOWN_ERROR
    }

    @Transactional
    public UserCreationResult createUser(String email, String password, String name) {
        if (password.length() < minPasswordLength || password.length() > maxPasswordLength) {
            return UserCreationResult.WRONG_PASSWORD_LENGTH;
        }
        if (!EmailValidator.getInstance().isValid(email)) {
            return UserCreationResult.INVALID_EMAIL;
        }
        final User existingUser = repository.findByEmail(email);
        if (existingUser != null) {
            return UserCreationResult.RESERVED_EMAIL;
        }
        final User user = repository.save(new User(email, password, name));
        return user == null ? UserCreationResult.UNKNOWN_ERROR : UserCreationResult.OK;
    }
}

还有我的pom.xml

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

    <groupId>com.somedomain</groupId>
    <artifactId>ws-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>My App</name>
    <description>My app's description</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

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

    <dependencies>
        <dependency>
            <groupId>commons-validator</groupId>
            <artifactId>commons-validator</artifactId>
            <version>1.6</version>
        </dependency>
        <dependency>
            <groupId>org.assertj</groupId>
            <artifactId>assertj-core</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

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


</project>

【问题讨论】:

    标签: spring spring-boot junit spring-data-jpa


    【解决方案1】:

    感谢question and answer,我能够在正确的配置下进行测试。

    在我的UserServiceTests 中,该服务基本上没有自动装配,因为这是@DataJpaTest 的预期行为:它不扫描常规bean。

    所以我对这个类使用了@SpringBootTest,并在两个测试类中都去掉了组件扫描。

    在那之后,我的一些服务测试失败了,因为使用@SpringBootTest,每次测试后数据库都不会重置。

    我在每次服务测试后添加了一个简单的存储库清理,一切正常。

    这个问题仍然存在:

    测试的顺序有什么关系?

    这是我的新测试课程:

    服务测试:

    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class UserServiceTests {
    
        @Autowired
        private UserService service;
    
        @Autowired
        private UserRepository repository;
    
        @After
        public void cleanUsers() {
            repository.deleteAll();
        }
    
        @Test
        public void testSuccessfullUserCreation() {
            UserCreationResult res = service.createUser("anything@anything.com", "1234567890", "Test");
            assertThat(res).isEqualTo(UserCreationResult.OK);
        }
    
        @Test
        public void testWrongEmailUserCreation() {
            UserCreationResult res = service.createUser("anything@anything", "1234567890", "Test");
            assertThat(res).isEqualTo(UserCreationResult.INVALID_EMAIL);
        }
    
        @Test
        public void testTooShortPasswordUserCreation() {
            String shortPassword =
                    String.join("", Collections.nCopies(UserService.minPasswordLength - 1, "0"));
            UserCreationResult res = service.createUser("anything@anything.com", shortPassword, "Test");
            assertThat(res).isEqualTo(UserCreationResult.WRONG_PASSWORD_LENGTH);
        }
    
        @Test
        public void testTooLongPasswordUserCreation() {
            String longPassword =
                    String.join("", Collections.nCopies(UserService.maxPasswordLength + 1, "0"));
            UserCreationResult res = service.createUser("anything@anything.com", longPassword, "Test");
            assertThat(res).isEqualTo(UserCreationResult.WRONG_PASSWORD_LENGTH);
        }
    
        @Test
        public void testMaxLengthPasswordUserCreation() {
            String maxPassword =
                    String.join("", Collections.nCopies(UserService.maxPasswordLength, "0"));
            UserCreationResult res = service.createUser("anything@anything.com", maxPassword, "Test");
            assertThat(res).isEqualTo(UserCreationResult.OK);
        }
    
        @Test
        public void testMinLengthPasswordUserCreation() {
            String minPassword =
                    String.join("", Collections.nCopies(UserService.minPasswordLength, "0"));
            UserCreationResult res = service.createUser("anything@anything.com", minPassword, "Test");
            assertThat(res).isEqualTo(UserCreationResult.OK);
        }
    
        @Test
        public void testReservedEmailUserCreation() {
            String email = "email@email.com";
            UserCreationResult res = service.createUser(email, "1234567890", "Test");
            assertThat(res).isEqualTo(UserCreationResult.OK);
            res = service.createUser(email, "1234567890", "Test");
            assertThat(res).isEqualTo(UserCreationResult.RESERVED_EMAIL);
        }
    }
    

    JPA 测试:

    @RunWith(SpringRunner.class)
    @DataJpaTest
    public class UserTests {
    
        @Autowired
        private TestEntityManager entityManager;
    
        @Autowired
        private UserRepository repository;
    
        @Test
        public void whenFindByEmail_thenReturnUser() {
            // given
            User user = new User("user@user.com", "12345678", "Some Name");
            entityManager.persist(user);
            entityManager.flush();
    
            // when
            User found = repository.findByEmail(user.getEmail());
    
            // then
            assertThat(found.getName()).isEqualTo(user.getName());
            assertThat(found.getEmail()).isEqualTo(user.getEmail());
            assertThat(found.getPasswordHash()).isEqualTo(user.getPasswordHash());
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-07-27
      • 2021-09-05
      • 2018-01-04
      • 2018-05-25
      • 2019-10-26
      • 2021-06-26
      • 2017-12-25
      • 1970-01-01
      • 2021-04-25
      相关资源
      最近更新 更多