Spring Boot Mockito (二)
基于第一篇Spring Boot Mockito (一)
这篇文章主要是讲解Spring boot 与 Mockito 集成持久层接口层单元测试。
1. 引入数据库 h2及其依赖包
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
2. 增加h2的属性配置 application.properties
spring.h2.console.enabled=true
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
3. 增加Order 的属性限制
public class Order {
//...
// 对Order增加注解
@NotNull
@NotBlank
@Size(max = 50)
@Column(length = 50)
private String name;
@NotNull
private Double price;
//...
4. 初始化数据
@Component
@RequiredArgsConstructor
public class InitData implements CommandLineRunner {
private final OrderRepository orderRepository;
@Override
public void run(String... args) throws Exception {
loadOrderData();
}
private void loadOrderData() {
if (orderRepository.count() == 0) {
Order order1 = Order.builder()
.id(1001L).name("Moon chairs")
.price(58.0)
.createTime(LocalDateTime.of(2024, 04, 01, 22, 10, 10))
.build();
Order order2 = Order.builder()
.id(1002L).name("Outdoor canopy black coating")
.price(98.0)
.createTime(LocalDateTime.of(2024, 04, 01, 22, 10, 10))
.build();
Order order3 = Order.builder()
.id(1003L).name("Outdoor canopy silver coating")
.price(48.0)
.createTime(LocalDateTime.of(2024, 04, 01, 22, 10, 10))
.build();
orderRepository.save(order1);
orderRepository.save(order2);
orderRepository.save(order3);
}
}
}
5. 新建持久层单元测试
@DataJpaTest
@Import(InitData.class)
public class OrderRepositoryTest {
@Autowired
OrderRepository orderRepository;
@Test
void test_findAllByNameLike() {
List<Order> list = orderRepository.findAllByNameLike("%Outdoor%");
assertEquals(2, list.size());
}
@Test
void test_findAllByNameLike_Empty() {
List<Order> list = orderRepository.findAllByNameLike("%Outdoor folding chair%");
assertEquals(0, list.size());
}
@Test
void test_findAllByPriceLessThan() {
List<Order> list = orderRepository.findAllByPriceLessThan(50d);
assertEquals(1, list.size());
}
@Test
void test_findAllByPriceLessThan_Empty() {
List<Order> list = orderRepository.findAllByPriceLessThan(10d);
assertEquals(0, list.size());
}
@Test
void test_saveOrder() {
Order order4 = Order.builder()
.id(1004L).name("Outdoor folding chair")
.price(28.0)
.createTime(LocalDateTime.of(2024, 04, 01, 22, 10, 10))
.build();
orderRepository.save(order4);
long count = orderRepository.count();
assertEquals(4, count);
}
@Test
void test_saveOrder_NameIsTooLong() {
Order order4 = Order.builder()
.id(1004L).name("Outdoor folding chair Outdoor folding chair Outdoor folding chair Outdoor folding chair Outdoor folding chair")
.price(28.0)
.createTime(LocalDateTime.of(2024, 04, 01, 22, 10, 10))
.build();
order4 = orderRepository.save(order4);
try {
orderRepository.flush();
fail("Name is null");
} catch (ConstraintViolationException cve) {
assertTrue(validate(cve, "size must be between 0 and 50", "name"));
}
}
@Test
void test_saveOrder_NameIsNull() {
Order order4 = Order.builder()
.id(1004L)
.price(28.0)
.createTime(LocalDateTime.of(2024, 04, 01, 22, 10, 10))
.build();
try {
order4 = orderRepository.save(order4);
orderRepository.flush();
fail("Name is null");
} catch (ConstraintViolationException cve) {
assertTrue(validate(cve, "must not be null", "name"));
}
}
private boolean validate(ConstraintViolationException cve, String message, String fieldName) {
return cve.getConstraintViolations().stream()
.anyMatch(e -> {
boolean hasMessage = e.getMessage().contains(message);
Iterator<Path.Node> itr = e.getPropertyPath().iterator();
boolean matchedFieldName = false;
while (itr.hasNext()) {
Path.Node pNode = itr.next();
matchedFieldName = pNode.getName().equals(fieldName);
if (matchedFieldName) {
break;
}
}
return hasMessage && matchedFieldName;
});
}
}