痛点
大家项目中是否遇到过需要编写测试方法的要求, 编写代码过程中,测试代码的广覆盖,往往能保证代码的健壮性。完善的测试用例也能便于后期迭代开发。而编写测试方法对象的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("110@163.com").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