Spring Boot 5多个JUnit JPA测试文件接线

时间:2018-01-20 23:18:09

标签: spring spring-boot junit spring-data-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("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测试文件,这些文件可以独立地进行适当的依赖注入?
  4. 这是我的服务类:

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

1 个答案:

答案 0 :(得分:0)

感谢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());
    }
}