痛點
大家項目中是否遇到過需要編寫測試方法的要求, 編寫代碼過程中,測試代碼的廣覆寫,往往能保證代碼的健壯性。完善的測試用例也能便于後期疊代開發。而編寫測試方法對象的mock資料,如果遇到一個多屬性對象,這項工作又是一個繁重且毫無意義的過程。
于是,下面的代碼,就占用了測試代碼的大部分篇幅:
@Test
public void testIntegral1(){
//
// System.out.println(JSONUtil.toJSON(integralService.queryIntegral(1)));
// IntegralOperateRequest request = IntegralOperateRequest.builder().orderNumber("11").accountId(1).point(100).type(1).build();
// System.out.println(JSONUtil.toJSON(integralService.reduceOrAddIntegral(request)));
//
// System.out.println(JSONUtil.toJSON(integralService.queryIntegral(1)));
//
// System.out.println(JSONUtil.toJSON(integralService.checkIntegralRisk(58865)));
AppShippingAddress entity = AppShippingAddress.builder().city("深圳市").country("china").firstName("jie").lastName("luo")
.address1("西麗街道").address2("創智雲城").email("[email protected]").phone("110").province("廣東省").userId(58865)
.provinceCode("111").site("US").zip("333").build();
OrderAddressUpdateDTO d= ClazzConverter.converterClass(entity,OrderAddressUpdateDTO.class);
d.setOrderNumber("62218929766150144");
System.out.println(appOrderService.updateAddressForBackend(d));
}
@Test
public void testIntegral() throws Exception {
// QueryOrderErpListDTO dto = new QueryOrderErpListDTO();
// dto.setPageSize(1);
// dto.setOrderNumber("1");
// dto.setSite("US");
// dto.setPageSize(2);
// dto.setEmail("77444");
// dto.setName("jieluo");
}
而且在新增場景中,我們兩次測試的資料不能重複。這個時候我們又要去重新制造我們的資料。
最近,一個開源項目讓我接觸到了PODAM,可以自動使用随機資料填充Java 對象原始屬性。
使用 PODAM
引入依賴:
<!--PODAM - Java 對象随機數填充器-屬性随機指派 Mock bean-->
<dependency>
<groupId>uk.co.jemos.podam</groupId>
<artifactId>podam</artifactId>
<version>[latest.version]</version>
</dependency>
實際使用
package govee.app.mall.mapper.mall;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.RandomUtil;
import govee.app.mall.BaseTest;
import govee.app.mall.pojo.constant.BuyTypeEnum;
import govee.app.mall.pojo.constant.SiteCurrencyEnum;
import govee.app.mall.pojo.vo.address.AddressVO;
import org.junit.jupiter.api.Test;
import uk.co.jemos.podam.api.PodamFactory;
import uk.co.jemos.podam.api.PodamFactoryImpl;
import uk.co.jemos.podam.api.RandomDataProviderStrategyImpl;
import javax.annotation.PostConstruct;
import java.util.Arrays;
import java.util.function.Consumer;
/**
* @author dongxu
* @create 2022-12-25 下午1:42
*/
public class StudyTest extends BaseTest {
private static final int RANDOM_STRING_LENGTH = 10;
private static final PodamFactory PODAM_FACTORY = new PodamFactoryImpl();
private PodamFactory factory;
/**
* 初始化一些類型的自定義資料
*/
static {
// 字元串
PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(String.class,
(dataProviderStrategy, attributeMetadata, map) -> randomString());
// Integer
PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(Integer.class, (dataProviderStrategy, attributeMetadata, map) -> {
// 如果是 status 的字段,傳回 0 或 1
if ("status".equals(attributeMetadata.getAttributeName())) {
return RandomUtil.randomEle(BuyTypeEnum.values()).getCode();
}
return RandomUtil.randomInt();
});
// Boolean
PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(Boolean.class, (dataProviderStrategy, attributeMetadata, map) -> {
// 如果是 deleted 的字段,傳回非删除
if ("deleted".equals(attributeMetadata.getAttributeName())) {
return false;
}
return RandomUtil.randomBoolean();
});
}
@PostConstruct
public void init() {
factory = new PodamFactoryImpl(new RandomDataProviderStrategyImpl());
}
public static String randomString() {
return RandomUtil.randomString(RANDOM_STRING_LENGTH);
}
/**
* 單獨處理個别字段
*
* @param clazz 目标類
* @param consumers 處理個别字段邏輯
* @param <T> 目标類類型
* @return 填充後的目标類執行個體
*/
@SafeVarargs
public static <T> T randomPojo(Class<T> clazz, Consumer<T>... consumers) {
T pojo = PODAM_FACTORY.manufacturePojo(clazz);
// 非空時,回調邏輯。通過它,可以實作 Pojo 的進一步處理
if (ArrayUtil.isNotEmpty(consumers)) {
Arrays.stream(consumers).forEach(consumer -> consumer.accept(pojo));
}
return pojo;
}
@Test
public void testRandomPojo() {
// 原始用法
AddressVO addressVO = PODAM_FACTORY.manufacturePojo(AddressVO.class);
System.out.println(addressVO.toString());
// 自定義屬性用法
AddressVO addressVO1 = StudyTest.randomPojo(AddressVO.class, a -> {
a.setCountry(RandomUtil.randomEle(SiteCurrencyEnum.values()).getSite());
});
System.out.println(addressVO1.toString());
// @PostConstruct 用法
AddressVO addressVO2 = factory.manufacturePojo(AddressVO.class);
System.out.println(addressVO2.toString());
}
}
Debug 1
Debug 2
Debug 3
最後挂一下github位址:PODAM