在前文《为领域对象编写业务一致的单元测试》,我以电子商城为例,介绍了如何为领域对象编写单元测试并保持业务一致性。本文介绍如何组织单元测试Setup步骤里的代码提高代码可读性。
以下是为Order编写的单元测试:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
| public class OrderStatusTest {
@Test
public void should_be_paying_status_when_create_order() {
// Setup and Exercise
var order = new Order(List.of(new OrderItem(Product.of("c1", "iPhone 16"), 3)));
// Verify
assertThat(order.getStatus()).isEqualTo(OrderStatus.Paying);
}
@Test
public void should_be_shipping_status_when_pay_order() {
// Setup
var order = new Order(List.of(new OrderItem(Product.of("c1", "iPhone 16"), 3)));
// Exercise
order.pay();
// Verify
assertThat(order.getStatus()).isEqualTo(OrderStatus.Shipping);
}
@Test
public void should_be_deliverying_status_when_ship_order() {
// Setup
var order = new Order(List.of(new OrderItem(Product.of("c1", "iPhone 16"), 3)));
order.pay();
// Exercise
order.ship();
// Verify
assertThat(order.getStatus()).isEqualTo(OrderStatus.Deliverying);
}
@Test
public void should_be_completed_status_when_delivery_order() {
// Setup
var order = new Order(List.of(new OrderItem(Product.of("c1", "iPhone 16"), 3)));
order.pay();
order.ship();
// Exercise
order.delivery();
// Verify
assertThat(order.getStatus()).isEqualTo(OrderStatus.Completed);
}
}
|
每个单元测试的测试过程可以归结如下:
1、测试新订单should_be_paying_status_when_create_order:

2、测试付款should_be_shipping_status_when_pay_order:

3、测试发货should_be_deliverying_status_when_ship_order:

4、测试收货should_be_completed_status_when_delivery_order:

但实际上单元测试的Setup步骤过于冗长且难以理解,例如构建待发货订单的代码无法直观地理解到当前状态为待发货:
1
2
| var order = new Order(List.of(new OrderItem(Product.of("c1", "iPhone 16"), 3)));
order.pay();
|
重新组织Setup代码
1、新建OrderFixtures,集中管理所有单元测试需要使用的Order对象,并提供可读性强的方法名:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| public class OrderFixtures {
public static Order newOrder() {
return new Order(List.of(new OrderItem(Product.of("c1", "iPhone 16"), 3)));
}
public static Order newPayingOrder() {
return new Order(List.of(new OrderItem(Product.of("c1", "iPhone 16"), 3)));
}
public static Order newShippingOrder() {
var order = new Order(List.of(new OrderItem(Product.of("c1", "iPhone 16"), 3)));
order.pay();
return order;
}
public static Order newDeliveryingOrder() {
var order = new Order(List.of(new OrderItem(Product.of("c1", "iPhone 16"), 3)));
order.pay();
order.ship();
return order;
}
}
|
2、OrderFixtures将为所有单元测试提供Order对象:

重构单元测试代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
| public class OrderStatusTest {
@Test
public void should_be_paying_status_when_create_order() {
// Setup and Exercise
var order = OrderFixtures.newOrder();
// Verify
assertThat(order.getStatus()).isEqualTo(OrderStatus.Paying);
}
@Test
public void should_be_shipping_status_when_pay_order() {
// Setup
var order = OrderFixtures.newPayingOrder();
// Exercise
order.pay();
// Verify
assertThat(order.getStatus()).isEqualTo(OrderStatus.Shipping);
}
@Test
public void should_be_deliverying_status_when_ship_order() {
// Setup
var order = OrderFixtures.newShippingOrder();
// Exercise
order.ship();
// Verify
assertThat(order.getStatus()).isEqualTo(OrderStatus.Deliverying);
}
@Test
public void should_be_completed_status_when_delivery_order() {
// Setup
var order = OrderFixtures.newDeliveryingOrder();
// Exercise
order.delivery();
// Verify
assertThat(order.getStatus()).isEqualTo(OrderStatus.Completed);
}
}
|