当前位置: 首页 > 知识库问答 >
问题:

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

黄宏旷
2023-03-14

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

@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);
    }
}

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

以下是我的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;
    }
}
<?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个答案

岳俊雅
2023-03-14

感谢这个问题和答案,我能够使我的测试工作与适当的配置。

在我的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());
    }
}
 类似资料:
  • 我正在尝试运行配置套件文件的并行测试。测试是针对使用Selenium的web应用程序。套件文件由多个测试组成。每个测试都包含多个测试类。每个测试中的第一个类用于初始化(@beforetest)WebDriver并关闭它(@aftertest)。WebDriver是静态的,以便将其传递给其他类(原因是我们需要从最后一个测试类结束的地方继续测试)。 当套件配置为按顺序运行测试时,测试将成功运行。但是当

  • 我正在与: Spring Framework JUnit 分级 我有这两个测试类 null Spring Boot/JUnit,为多个配置文件运行所有单元测试 但是我希望避免通过或使用命令,它通过类保持控件。

  • 我使用Jest框架,并有一个测试套件。我想关闭/跳过我的一个测试。 谷歌文档并没有给我答案。 你知道要查的答案或信息来源吗?

  • 问题内容: 我试图将来自多个文件的所有测试合并到一个文件中,如下所示: 我很确定这不是参加测试的最佳方式,我很难找到如何执行此操作的示例: 问题答案: 如果你想包含多个模块 到 您的层次结构就像你在你的问题做什么,你在做什么是相当多的 它 ,除非你想要写摩卡自定义测试装载机。编写自定义加载器不会比已有代码容易或使代码更清晰。 这是我将如何更改某些事情的示例。本示例中的子目录组织为: : 该功能只是

  • 我正在从事一个相当大的项目,其中包括一组自定义JavaFX组件。对于每个需要重用的自定义组件,我已经开始使用JemmyFX和JUnit编写一组自动化测试。在开发过程中,我从Eclipse Juno内部运行这些。 事实证明,一次运行整个测试套件很困难。这个问题似乎源于这样一个事实,因为我想测试多个组件,所以理想情况下,我会为每个组件运行不同的应用程序(以便在一个组件上执行的测试不会影响其他测试)。