了解单元测试参考文章高质量单元测试要求和依据阿里巴巴编码规范的Java单元测试示例-CSDN博客
java 写单元测试的常用技术组件和mock示例-CSDN博客
单元测试场景示例:
1.方法输入输出验证:
测试一个计算类的方法,如加法、减法、乘法和除法运算是否正确。
2.边界条件测试:
测试一个函数在处理边界数据时的行为,例如列表为空或只有一个元素时的情况,或者数学函数中除数为零等非法情况。
3.错误/异常处理测试:
确保当程序遇到预期错误(如文件未找到、网络连接失败、无效用户输入)时,会抛出适当的异常,并且后续逻辑能够正常执行。
4.集成测试中的部分隔离:
使用mock对象来模拟依赖的服务或组件,确保即使这些依赖不可用或有未知行为,被测试代码也能按预期工作。
5.多线程和并发测试:
使用@Test
注解的org.junit.jupiter.api.RepeatedTest
结合并发工具,测试多线程环境下的类或方法的线程安全性和正确性。
6.数据库操作测试:
对于涉及数据库操作的方法,可以使用像H2这样的内存数据库,配合Spring的@DataJpaTest
或Hibernate的测试工具进行单元测试。
每个测试都应该独立运行且结果可预测,通过设定明确的前置条件、执行动作并验证结果,确保单个模块的功能完整性。
Java编写单元测试的常用技术实现如下,供探讨学习:
1.JUnit 5:
JUnit 是Java中最广泛使用的单元测试框架,最新版本是JUnit 5,它提供了丰富的注解、条件测试、参数化测试、异常测试等功能。
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class CalculatorTest {
@Test
void testAddition() {
Calculator calculator = new Calculator();
int result = calculator.add(2, 3);
assertEquals(5, result, "2 + 3 should equal 5");
}
@Test
void testDivisionByZero() {
Calculator calculator = new Calculator();
assertThrows(ArithmeticException.class, () -> calculator.divide(1, 0));
}
}
2.Mocking Frameworks:
Mockito 和 EasyMock 可用于模拟对象行为以隔离被测试代码与其他依赖项的交互。
import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.*;
class UserServiceTest {
@Test
void testUserRegistration() {
UserRepository repo = mock(UserRepository.class);
when(repo.save(any(User.class))).thenReturn(true);
UserService userService = new UserService(repo);
User newUser = new User("testUser", "password");
boolean registrationSuccess = userService.register(newUser);
verify(repo).save(newUser);
assertTrue(registrationSuccess);
}
}
3.Assertion Libraries:
Hamcrest 或 AssertJ 提供了更丰富和可读性更强的断言表达式。
import static org.assertj.core.api.Assertions.assertThat;
@Test
void testArraySorting() {
Integer[] numbers = {3, 1, 4, 1, 5, 9};
Arrays.sort(numbers);
assertThat(numbers).containsExactly(1, 1, 3, 4, 5, 9);
}
Spring boot maven工程常会结合Spring Boot Test和JUnit5框架,单元测试代码示例实现:
1. 测试无依赖的简单服务类
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class SimpleServiceTest {
private final SimpleService simpleService = new SimpleService();
@Test
void testSimpleFunction() {
String result = simpleService.concatenate("Hello", "World");
assertEquals("HelloWorld", result);
}
}
2. 使用@SpringBootTest注解进行集成测试(包括自动注入)
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import static org.junit.jupiter.api.Assertions.assertNotNull;
@SpringBootTest
class UserServiceTest {
@Autowired
private UserService userService;
@Test
void testUserCreation() {
User user = userService.createUser("testuser", "password");
assertNotNull(user.getId(), "User ID should not be null after creation");
}
}
3. 使用Mockito模拟依赖项进行单元测试
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class OrderServiceTest {
@Mock
private ProductService productService;
@InjectMocks
private OrderService orderService;
@BeforeEach // JUnit5中的初始化方法
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
void testOrderTotalWithMockedProduct() {
Product product = new Product(1L, "Item", 10.0);
Mockito.when(productService.getProductById(1L)).thenReturn(product);
double total = orderService.calculateOrderTotal(1L, 2);
assertEquals(20.0, total, 0.001, "Order total calculation is incorrect");
Mockito.verify(productService).getProductById(1L);
}
}
4. 数据库操作的单元测试(使用Spring Data JPA与内嵌数据库如H2)
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import static org.assertj.core.api.Assertions.assertThat;
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) // 使用内嵌H2数据库
class UserRepositoryTest {
@Autowired
private UserRepository userRepository;
@Test
void whenFindByUsername_thenReturnUser() {
// 假设已有用户数据
userRepository.save(new User("testuser", "password"));
Optional<User> foundUser = userRepository.findByUsername("testuser");
assertThat(foundUser).isPresent();
assertThat(foundUser.get().getUsername()).isEqualTo("testuser");
}
}