在Java测试栈上打造你的多功能工具

代码的可测试性在高效代码设计中确保了诸多优点,如可维护性;它有助于文档编写,使得重构和构建演进式设计/架构更为简便。这一点毋庸置疑,但一个好的测试栈应如何启动一个项目呢?本视频将阐述使用Java启动项目所需的最小测试栈。

首先,当我们谈论“最小”时,必须明白测试栈中没有万能钥匙。最终,我们需要包含或移除依赖,特别是在处理遗留代码时。基于此,我将分享我个人在Java中最喜欢的测试栈,并将其作为从头开始的最小推荐配置:

  • JUnit-Jupiter:JUnit的第五版与前一版不兼容,但因其引入了众多特性,尤其是创建自定义扩展的能力,这一改变是值得的。

  • Mockito:一个在Java中极为流行的模拟框架。其广泛的社区支持使得它能够与JUnit-Jupiter等工具结合,扩展出多种功能。

  • AssertJ: 如果你和我一样钟爱流畅的API,那么AssertJ对你来说是一个绝佳的库。

通过Maven项目,你可以添加这些库的依赖:

XML

 

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-engine</artifactId>
    <version>${junit.version}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-params</artifactId>
    <version>${junit.version}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>${mockito.verson}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-junit-jupiter</artifactId>
    <version>${mockito.verson}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.assertj</groupId>
    <artifactId>assertj-core</artifactId>
    <version>${assertj.verson}</version>
    <scope>test</scope>
</dependency>

以足球锦标赛联赛为背景,其中一支球队应有11名球员,且每位球员的名字在联赛中必须唯一。我们可以就此展开测试。

从JMockito和测试开始,我们需要测试一个服务,该服务需要检查数据库中是否存在某个名字以执行逻辑。此时,我们无需也不希望进行集成测试。

我们希望专注于业务逻辑,因此不想测试数据库或框架,只关注自己的代码。因此,我们将用两种场景来模拟仓库:当名字存在和不存在时。

利用Mockito与JUnit-Jupiter的集成,你可以仅通过注解注入模拟对象。下面的代码展示了使用JMockito的测试,我们无需数据库,也无需偏离焦点去测试业务逻辑。

Java

 

@ExtendWith(MockitoExtension.class)
class ChampionshipServiceTest {

    @Mock
    private ChampionRepository repository;

    @InjectMocks
    private ChampionshipService service;

    @Test
    public void shouldRegister() {
        Mockito.when(repository.existByName("Bahia")).thenReturn(false);
        Team bahia = Team.of("Bahia");
        service.register(bahia);

        Mockito.verify(repository).existByName("Bahia");
    }
    @Test
    @DisplayName("should return an exception when there is a team with a name")
    public void shouldThrownAnExceptionWhenTeamNameExists() {
        Mockito.when(repository.existByName("Bahia")).thenReturn(true);
        Team bahia = Team.of("Bahia");
        Assertions.assertThrows(IllegalArgumentException.class, () ->
                service.register(bahia));

        Mockito.verify(repository).existByName("Bahia");
    }
}

AssertJ通过其支持的流畅API简化了断言的理解过程,使得测试集合、映射或单一实例变得直观。例如,我们可以利用它来验证向团队中添加玩家的操作。

Java

 

@Test
public void shouldCreatePlayers() {
    Team bahia = Team.of("Bahia");
    bahia.add(Player.of("Neymar", "Santos", 10));
    bahia.add(Player.of("Cristiano Ronaldo", "Lisbon", 10));

    org.assertj.core.api.Assertions.assertThat(bahia.players())
            .hasSize(2)
            .map(Player::name)
            .contains("Neymar", "Cristiano Ronaldo");
}

更多详情请观看此视频获取。

要点总结:

  • A minimum test stack to start Java

  • 深入了解JUnit及其优势所在

  • 通过JMockito探索模拟对象的应用

  • 运用流畅API的AssertJ美化你的测试代码

Source:
https://dzone.com/articles/creating-your-swiss-army-knife-on-java-test-stack