代码的可测试性在高效代码设计中确保了诸多优点,如可维护性;它有助于文档编写,使得重构和构建演进式设计/架构更为简便。这一点毋庸置疑,但一个好的测试栈应如何启动一个项目呢?本视频将阐述使用Java启动项目所需的最小测试栈。
首先,当我们谈论“最小”时,必须明白测试栈中没有万能钥匙。最终,我们需要包含或移除依赖,特别是在处理遗留代码时。基于此,我将分享我个人在Java中最喜欢的测试栈,并将其作为从头开始的最小推荐配置:
-
JUnit-Jupiter:JUnit的第五版与前一版不兼容,但因其引入了众多特性,尤其是创建自定义扩展的能力,这一改变是值得的。
-
Mockito:一个在Java中极为流行的模拟框架。其广泛的社区支持使得它能够与JUnit-Jupiter等工具结合,扩展出多种功能。
-
AssertJ: 如果你和我一样钟爱流畅的API,那么AssertJ对你来说是一个绝佳的库。
通过Maven项目,你可以添加这些库的依赖:
<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的测试,我们无需数据库,也无需偏离焦点去测试业务逻辑。
@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简化了断言的理解过程,使得测试集合、映射或单一实例变得直观。例如,我们可以利用它来验证向团队中添加玩家的操作。
@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