Map<Long, String> languageMap = new HashMap<>(MapHelper.DEFAULT);languageMap.put(1L, "Java");languageMap.put(2L, "C++");languageMap.put(3L, "Python");languageMap.put(4L, "JavaScript");... // 约几十行Whitebox.setInternalState(developmentService, "languageMap", languageMap);
List<UserCreateVO> userCreateList = new ArrayList<>();UserCreateVO userCreate0 = new UserCreateVO();userCreate0.setName("Changyi");userCreate0.setTitle("Java Developer");... // 约几十行userCreateList.add(userCreate0);UserCreateVO userCreate1 = new UserCreateVO();userCreate1.setName("Tester");userCreate1.setTitle("Java Tester");... // 约几十行userCreateList.add(userCreate1);... // 约几十条userService.batchCreate(userCreateList);
Long companyId = 1L;List<UserDO> userList = new ArrayList<>();UserDO user0 = new UserDO();user0.setId(1L);user0.setName("Changyi");user0.setTitle("Java Developer");... // 约几十行userList.add(user0);UserDO user1 = new UserDO();user1.setId(2L);user1.setName("Tester");user1.setTitle("Java Tester");... // 约几十行userList.add(user1);... // 约几十条Mockito.doReturn(userList).when(userDAO).queryByCompanyId(companyId);
Long companyId = 1L;List<UserVO> userList = userService.queryByCompanyId(companyId);UserVO user0 = userList.get(0);Assert.assertEquals("name不一致", "Changyi", user0.getName());Assert.assertEquals("title不一致", "Java Developer", user0.getTitle());... // 约几十行UserVO user1 = userList.get(1);Assert.assertEquals("name不一致", "Tester", user1.getName());Assert.assertEquals("title不一致", "Java Tester", user1.getTitle());... // 约几十行... // 约几十条
ArgumentCaptor<List<UserDO>> userCreateListCaptor = CastUtils.cast(ArgumentCaptor.forClass(List.class));Mockito.verify(userDAO).batchCreate(userCreateListCaptor.capture());List<UserDO> userCreateList = userCreateListCaptor.getValue();UserDO userCreate0 = userCreateList.get(0);Assert.assertEquals("name不一致", "Changyi", userCreate0.getName());Assert.assertEquals("title不一致", "Java Developer", userCreate0.getTitle());... // 约几十行UserDO userCreate1 = userCreateList.get(1);Assert.assertEquals("name不一致", "Tester", userCreate1.getName());Assert.assertEquals("title不一致", "Java Tester", userCreate1.getTitle());... // 约几十行... // 约几十条
String text = ResourceHelper.getResourceAsString(getClass(), path + "languageMap.json");Map<Long, String> languageMap = JSON.parseObject(text, new TypeReference<Map<Long, String>>() {});Whitebox.setInternalState(mobilePhoneService, "languageMap", languageMap);
{1:"Java",2:"C++",3:"Python",4:"JavaScript"...}
String text = ResourceHelper.getResourceAsString(getClass(), path + "userCreateList.json");List<UserCreateVO> userCreateList = JSON.parseArray(text, UserCreateVO.class);userService.batchCreate(userCreateList);
[{"name":"Changyi","title":"Java Developer"...},{"name":"Tester","title":"Java Tester"...},...]
Long companyId = 1L;String text = ResourceHelper.getResourceAsString(getClass(), path + "userList.json");List<UserDO> userList = JSON.parseArray(text, UserDO.class);Mockito.doReturn(userList).when(userDAO).queryByCompanyId(companyId);
[{"id":1,"name":"Changyi","title":"Java Developer"...},{"id":2,"name":"Tester","title":"Java Tester"...},...]
Long companyId = 1L;List<UserVO> userList = userService.queryByCompanyId(companyId);String text = ResourceHelper.getResourceAsString(getClass(), path + "userList.json");Assert.assertEquals("用户列表不一致", text, JSON.toJSONString(userList));
[{"name":"Changyi","title":"Java Developer"...},{"name":"Tester","title":"Java Tester"...},...]
ArgumentCaptor<List<UserDO>> userCreateListCaptor = CastUtils.cast(ArgumentCaptor.forClass(List.class));Mockito.verify(userDAO).batchCreate(userCreateListCaptor.capture());String text = ResourceHelper.getResourceAsString(getClass(), path + "userCreateList.json");Assert.assertEquals("用户创建列表不一致", text, JSON.toJSONString(userCreateListCaptor.getValue()));
[{"name":"Changyi","title":"Java Developer"...},{"name":"Tester","title":"Java Tester"...},...]
String text = ResourceHelper.getResourceAsString(getClass(), path + "userCreateList.json");List<UserCreateVO> userCreateList = JSON.parseArray(text, UserCreateVO.class);userService.batchCreate(userCreateList);
git checkout developerror: xxx/xxx: Filename too long
git add .error: open("xxx/xxx"): Filename too longerror: unable to index file 'xxx/xxx'fatal: adding files failed
git config --system core.longpaths true
/** * 用户服务类 */public class UserService {
/** 服务相关 */ /** 用户DAO */ private UserDAO userDAO; /** 标识生成器 */ private IdGenerator idGenerator;
/** 参数相关 */ /** 可以修改 */ ("${userService.canModify}") private Boolean canModify;
/** * 创建用户 * * @param userCreate 用户创建 * @return 用户标识 */ public Long createUser(UserVO userCreate) { // 获取用户标识 Long userId = userDAO.getIdByName(userCreate.getName());
// 根据存在处理 // 根据存在处理: 不存在则创建 if (Objects.isNull(userId)) { userId = idGenerator.next(); UserDO userCreateDO = new UserDO(); userCreateDO.setId(userId); userCreateDO.setName(userCreate.getName()); userDAO.create(userCreateDO); } // 根据存在处理: 已存在可修改 else if (Boolean.TRUE.equals(canModify)) { UserDO userModifyDO = new UserDO(); userModifyDO.setId(userId); userModifyDO.setName(userCreate.getName()); userDAO.modify(userModifyDO); } // 根据存在处理: 已存在禁修改 else { throw new UnsupportedOperationException("不支持修改"); }
// 返回用户标识 return userId; }
}
/** * 用户服务测试类 */(PowerMockRunner.class)public class UserServiceTest {
/** 模拟依赖对象 */ /** 用户DAO */ private UserDAO userDAO; /** 标识生成器 */ private IdGenerator idGenerator;
/** 定义测试对象 */ /** 用户服务 */ private UserService userService;
/** 定义静态常量 */ /** 资源路径 */ private static final String RESOURCE_PATH = "testUserService/";
/** * 在测试之前 */ public void beforeTest() { // 注入依赖对象 Whitebox.setInternalState(userService, "canModify", Boolean.TRUE); }
/** * 测试: 创建用户-创建 */ public void testCreateUserWithCreate() { // 模拟依赖方法 // 模拟依赖方法: userDAO.getByName Mockito.doReturn(null).when(userDAO).getIdByName(Mockito.anyString()); // 模拟依赖方法: idGenerator.next Long userId = 1L; Mockito.doReturn(userId).when(idGenerator).next();
// 调用测试方法 String path = RESOURCE_PATH + "testCreateUserWithCreate/"; String text = ResourceHelper.getResourceAsString(getClass(), path + "userCreateVO.json"); UserVO userCreate = JSON.parseObject(text, UserVO.class); Assert.assertEquals("用户标识不一致", userId, userService.createUser(userCreate));
// 验证依赖方法 // 验证依赖方法: userDAO.getByName Mockito.verify(userDAO).getIdByName(userCreate.getName()); // 验证依赖方法: idGenerator.next Mockito.verify(idGenerator).next(); // 验证依赖方法: userDAO.create ArgumentCaptor<UserDO> userCreateCaptor = ArgumentCaptor.forClass(UserDO.class); Mockito.verify(userDAO).create(userCreateCaptor.capture()); text = ResourceHelper.getResourceAsString(getClass(), path + "userCreateDO.json"); Assert.assertEquals("用户创建不一致", text, JSON.toJSONString(userCreateCaptor.getValue()));
// 验证依赖对象 // 验证依赖对象: idGenerator, userDAO Mockito.verifyNoMoreInteractions(idGenerator, userDAO); }
/** * 测试: 创建用户-修改 */ public void testCreateUserWithModify() { // 模拟依赖方法 // 模拟依赖方法: userDAO.getByName Long userId = 1L; Mockito.doReturn(userId).when(userDAO).getIdByName(Mockito.anyString());
// 调用测试方法 String path = RESOURCE_PATH + "testCreateUserWithModify/"; String text = ResourceHelper.getResourceAsString(getClass(), path + "userCreateVO.json"); UserVO userCreate = JSON.parseObject(text, UserVO.class); Assert.assertEquals("用户标识不一致", userId, userService.createUser(userCreate));
// 验证依赖方法 // 验证依赖方法: userDAO.getByName Mockito.verify(userDAO).getIdByName(userCreate.getName()); // 验证依赖方法: userDAO.modify ArgumentCaptor<UserDO> userModifyCaptor = ArgumentCaptor.forClass(UserDO.class); Mockito.verify(userDAO).modify(userModifyCaptor.capture()); text = ResourceHelper.getResourceAsString(getClass(), path + "userModifyDO.json"); Assert.assertEquals("用户修改不一致", text, JSON.toJSONString(userModifyCaptor.getValue()));
// 验证依赖对象 // 验证依赖对象: idGenerator Mockito.verifyZeroInteractions(idGenerator); // 验证依赖对象: userDAO Mockito.verifyNoMoreInteractions(userDAO); }
/** * 测试: 创建用户-异常 */ public void testCreateUserWithException() { // 注入依赖对象 Whitebox.setInternalState(userService, "canModify", Boolean.FALSE);
// 模拟依赖方法 // 模拟依赖方法: userDAO.getByName Long userId = 1L; Mockito.doReturn(userId).when(userDAO).getIdByName(Mockito.anyString());
// 调用测试方法 String path = RESOURCE_PATH + "testCreateUserWithException/"; String text = ResourceHelper.getResourceAsString(getClass(), path + "userCreateVO.json"); UserVO userCreate = JSON.parseObject(text, UserVO.class); UnsupportedOperationException exception = Assert.assertThrows("返回异常不一致", UnsupportedOperationException.class, () -> userService.createUser(userCreate)); Assert.assertEquals("异常消息不一致", "不支持修改", exception.getMessage());
// 验证依赖方法 // 验证依赖方法: userDAO.getByName Mockito.verify(userDAO).getIdByName(userCreate.getName());
// 验证依赖对象 // 验证依赖对象: idGenerator Mockito.verifyZeroInteractions(idGenerator); // 验证依赖对象: userDAO Mockito.verifyNoMoreInteractions(userDAO); }
}
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> ...
<!-- 属性管理 --> <properties> ... <junit.version>4.13.1</junit.version> <mockito.version>3.3.3</mockito.version> <powermock.version>2.0.9</powermock.version> </properties>
<!-- 依赖管理 --> <dependencyManagement> <dependencies> ... <!-- PowerMock --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>${mockito.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <version>${powermock.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito2</artifactId> <version>${powermock.version}</version> <scope>test</scope> </dependency> </dependencies> </dependencyManagement>
<!-- 构建管理 --> <build> <pluginManagement> <plugins> ... <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>2.6</version> <executions> ... <execution> <id>copy-test-resources</id> <phase>compile</phase> <goals> <goal>copy-resources</goal> </goals> <configuration> <encoding>UTF-8</encoding> <outputDirectory>${project.build.directory}/test-classes</outputDirectory> <resources> <resource> <directory>src/test/java</directory> <includes> <include>**/*.txt</include> <include>**/*.csv</include> <include>**/*.json</include> <include>**/*.properties</include> </includes> </resource> <resource> <directory>src/test/resources</directory> <includes> <include>**/*.txt</include> <include>**/*.csv</include> <include>**/*.json</include> <include>**/*.properties</include> </includes> </resource> </resources> </configuration> </execution> </executions> </plugin> </plugins> </pluginManagement> </build></project>
在属性配置中,配置了单元测试所依赖的包版本;
在依赖配置中,配置了单元测试所依赖的包名称;
在构建配置中,配置了编译时需要拷贝目录下的资源文件(如果有其它的资源文件格式,需要在pom中配置添加)。
/** * 资源辅助类 */public final class ResourceHelper {
/** * 构造方法 */ private ResourceHelper() { throw new UnsupportedOperationException(); }
/** * 以字符串方式获取资源 * * @param clazz 类 * @param name 资源名称 * @return 字符串 */ public static <T> String getResourceAsString(Class<T> clazz, String name) { try (InputStream is = clazz.getResourceAsStream(name)) { return IOUtils.toString(is, StandardCharsets.UTF_8); } catch (IOException e) { throw new RuntimeException(String.format("以字符串方式获取资源(%s)异常", name), e); } }
}
[{"name":"Changyi","title":"Java Developer"...},{"name":"Tester","title":"Java Tester"...},...]
public static void main(String[] args) { List<UserCreateVO> userCreateList = new ArrayList<>(); UserCreateVO userCreate0 = new UserCreateVO(); userCreate0.setName("Changyi"); userCreate0.setTitle("Java Developer"); ... // 约几十行 userCreateList.add(userCreate0); UserCreateVO userCreate1 = new UserCreateVO(); userCreate1.setName("Tester"); userCreate1.setTitle("Java Tester"); ... // 约几十行 userCreateList.add(userCreate1); ... // 约几十条 System.out.println(JSON.toJSONString(userCreateList));}
[{"name":"Changyi","title":"Java Developer"...},{"name":"Tester","title":"Java Tester"...},...]
2021-08-31 18:55:40,867 INFO [UserService.java:34] - 根据公司标识(1)查询所有用户:[{"id":1,"name":"Changyi","title":"Java Developer"...},{"id":2,"name":"Tester","title":"Java Tester"...},...]
/** * 用户DAO测试类 */(PandoraBootRunner.class)(SpringJUnit4ClassRunner.class)(classes = {ExampleApplication.class})public class UserDaoTest {
/** 用户DAO */ private UserDAO userDAO;
/** * 测试: 根据公司标识查询 */ public void testQueryByCompanyId() { Long companyId = 1L; List<UserDO> userList = userDAO.queryByCompanyId(companyId); log.info("userList={}", JSON.toJSONString(userList)); }
}
2021-08-31 18:55:40,867 INFO [UserDaoTest.java:24] - userList=[{"id":1,"name":"Changyi","title":"Java Developer"...},{"id":2,"name":"Tester","title":"Java Tester"...},...]
public void batchCreate(List<UserCreate> createList) { List<UserDO> userList = createList.stream() .map(UserService::convertUser).collect(Collectors.toList()); userDAO.batchCreate(userList);}
public void testBatchCreate() { // 调用测试方法 List<UserCreate> createList = ...; userService.batchCreate(createList); // 验证测试方法 ArgumentCaptor<List<UserDO>> userListCaptor = CastUtils.cast(ArgumentCaptor.forClass(List.class)); Mockito.verify(userDAO).batchCreate(userListCaptor.capture()); Assert.assertEquals("用户列表不一致", "", JSON.toJSONString(userListCaptor.getValue()));}
org.junit.ComparisonFailure: 用户列表不一致 expected:<[]> but was:<[[{"name":"Changyi","title":"Java Developer"...},{"name":"Tester","title":"Java Tester"...},...]]>
UserVO user = ...;String text = JSON.toJSONString(user);
UserVO[] users = ...;String text = JSON.toJSONString(users);
List<UserVO> userList = ...;String text = JSON.toJSONString(userList);
Map<Long, UserVO> userMap = ...;String text = JSON.toJSONString(userMap, SerializerFeature.MapSortField);
Result<UserVO> result = ...;String text = JSON.toJSONString(result);
UserVO user = ...;SimplePropertyPreFilter filter = new SimplePropertyPreFilter();filter.getIncludes().addAll(Arrays.asList("id", "name"));String text = JSON.toJSONString(user, filter);
List<UserVO> userList = ...;SimplePropertyPreFilter filter = new SimplePropertyPreFilter(UserVO.class);filter.getIncludes().addAll(Arrays.asList("id", "name"));String text = JSON.toJSONString(userList, filter);
Pair<UserVO, CompanyVO> userCompanyPair = ...;SimplePropertyPreFilter userFilter = new SimplePropertyPreFilter(UserVO.class);userFilter.getUncludes().addAll(Arrays.asList("id", "name"));SimplePropertyPreFilter companyFilter = new SimplePropertyPreFilter(CompanyVO.class);companyFilter.getIncludes().addAll(Arrays.asList("id", "name"));String text = JSON.toJSONString(userCompanyPair, new SerializeFilter[]{userFilter, companyFilter});
UserVO user = ...;SimplePropertyPreFilter filter = new SimplePropertyPreFilter();filter.getExcludes().addAll(Arrays.asList("gmtCreate", "gmtModified"));String text = JSON.toJSONString(user, filter);
List<UserVO> userList = ...;SimplePropertyPreFilter filter = new SimplePropertyPreFilter(UserVO.class);filter.getExcludes().addAll(Arrays.asList("gmtCreate", "gmtModified"));String text = JSON.toJSONString(userList, filter);
Pair<UserVO, CompanyVO> userCompanyPair = ...;SimplePropertyPreFilter userFilter = new SimplePropertyPreFilter(UserVO.class);userFilter.getExcludes().addAll(Arrays.asList("gmtCreate", "gmtModified"));SimplePropertyPreFilter companyFilter = new SimplePropertyPreFilter(CompanyVO.class);companyFilter.getExcludes().addAll(Arrays.asList("createTime", "modifyTime"));String text = JSON.toJSONString(userCompanyPair, new SerializeFilter[]{userFilter, companyFilter});
Geometry geometry = ...;SerializeConfig.getGlobalInstance().put(Geometry.class, new GeometrySerializer());String text = JSON.toJSONString(geometry);
Geometry geometry = ...;SerializeConfig config = new SerializeConfig();config.put(Geometry.class, new GeometrySerializer());String text = JSON.toJSONString(geometry, config);
public class User { ... (serializeUsing = GeometrySerializer.class) private Geometry location; ...}
User user = ...;String text = JSON.toJSONString(user);
String text = ...;UserVO user = JSON.parseObject(text, UserVO.class);
String text = ...;UserVO[] users = JSON.parseObject(text, UserVO[].class);
String text = ...;List<UserVO> userList = JSON.parseArray(text, UserVO.class);
String text = ...;Set<UserVO> userSet = JSON.parseObject(text, new TypeReference<Set<UserVO>>() {});
String text = ...;Map<Long, UserVO> userList = JSON.parseObject(text, new TypeReference<Map<Long, UserVO>>() {});
String text = ...;Result<UserVO> result = JSON.parseArray(text, new TypeReference<Result<UserVO>>() {});
String text = ...;UserVO user = JSON.parseObject(text, UserVO.class, Feature.SupportNonPublicField);
com.alibaba.Fastjson.JSONException: default constructor not found. class com.example.User
String text = ...;User user = JSON.parseObject(text, User.UserBuilder.class, Feature.SupportNonPublicField).build();
class User { private Long id; private String name; public User(Long id) { this.id = id; }}
String text = "{\"id\":123,\"name\":\"test\"}";User user = JSON.parseObject(text, User.class); // 会丢失name值
String text = ...;ParserConfig.getGlobalInstance().putDeserializer(Geometry.class, new GeometryDeserializer());Geometry geometry = JSON.parseObject(text, Geometry.class);
String text = ...;ParserConfig config = new ParserConfig();config.putDeserializer(Geometry.class, new GeometryDeserializer());Geometry geometry = JSON.parseObject(text, Geometry.class, config);
public class User { ... private Geometry location; ...}
String text = ...;User user = JSON.parseObject(text, User.class);
public void batchCreate(List<UserCreate> createList) { userDAO.batchCreate(createList);}
public void testBatchCreate() { // 调用测试方法 List<UserCreate> createList = new ArrayList<>(); userService.batchCreate(createList); // 验证测试方法 Mockito.verify(userDAO).batchCreate(createList);}
public List<UserVO> queryByCompanyId(Long companyId) { return userDAO.queryByCompanyId(companyId);}
public void testQueryByCondition() { // 模拟依赖方法 Long companyId = 1L; List<UserVO> userList = new ArrayList<>(); Mockito.doReturn(userList).when(userDAO).queryByCompanyId(companyId); // 调用测试方法 Assert.assertEquals("用户列表不一致", userList, userService.queryByCompanyId(companyId));}
public void handleResult(Result<UserVO> result) { if (!result.isSuccess()) { metaProducer.sendCouponMessage(result.getData()); }}
public void testHandleResultWithSuccess() { // 调用测试方法 UserVO user = new UserVO(); Result<UserVO> result = Result.success(user); userService.handleResult(result);
// 验证依赖方法 Mockito.verify(metaProducer).sendCouponMessage(user);}
public UserVO get(Long userId) { Result<UserVO> result = userHsfService.get(userId); if (!result.isSuccess()) { throw new ExmapleException(String.format("获取用户(%s)失败:%s", userId, result.getMessage())); } return result.getData();}
public void testGetWithSuccess() { // 模拟依赖方法 Long userId = 123L; UserVO user = UserVO(); Mockito.doReturn(Result.success(user)).when(userHsfService).get(userId); // 调用测试方法 Assert.assertEquals("用户信息不一致", user, userService.get(userId));}
public void create(UserCreate userCreate) { Boolean exist = userDAO.existByName(userCreate.getName()); if (Boolean.TRUE.equals(exist)) { throw new ExmapleException(String.format("用户(%s)已存在", userCreate.getName())); } userDAO.create(userCreate);}
public void testCreateWithException() { UserCreate userCreate = new UserCreate(); userCreate.setName("changyi"); ExmapleException exception = Assert.assertThrows("异常类型不一致", ExmapleException.class, () -> userService.create(userCreate)); Assert.assertEquals("异常消息不一致", String.format("用户(%s)已存在", userCreate.getName()), exception.getMessage());}
public boolean isVip(Long userId) { UserDO user = userDAO.get(userId); return VIP_ROLE_ID_SET.contains(user.getRoleId());}
@Testpublic void testIsVipWithTrue() { // 模拟依赖方法 Long userId = 123L; UserDO user = new UserDO(); user.setRoleId(VIP_ROLE_ID); Mockito.doReturn(user).when(userDAO).get(userId);
// 调用测试方法 Assert.assertTrue("返回值不为真", userService.isVip());}
String text = ResourceHelper.getResourceAsString(getClass(), path + "recordList.json");Record[] records = JSON.parseObject(text, Record[].class);Mockito.doReturn(records[0], ArrayUtils.subarray(records, 1, records.length)).when(recordReader).read();
String text = ResourceHelper.getResourceAsString(getClass(), path + "roleMap.json");Map<Long, String> roleIdMap = JSON.parseObject(text, new TypeReference<Map<Long, String>>() {});Mockito.doAnswer(invocation -> userMap.get(invocation.getArgument(0))).when(roleService).get(roleId);
ArgumentCaptor<UserCreateVO> userCreateCaptor = ArgumentCaptor.forClass(UserCreateVO.class);Mockito.verify(userDAO, Mockito.atLeastOnce()).create(userCreateCaptor.capture());String text = ResourceHelper.getResourceAsString(getClass(), path + "userCreateList.json");Assert.assertEquals("用户创建列表不一致", text, JSON.toJSONString(userCreateCaptor.getAllValues()));