在前面的文章中(Spring Boot 2 实践记录之 Powermock 和 SpringBootTest)提到了使用 Powermock 结合 SpringBootTest、WebMvcTest 来 Mock Service、Controller 中的 静态类和静态方法。

但此法有两个弊端,一是这样的单元测试运行速度慢,二是时不时会出现测试运行停顿的情况。

一个可选的方案就是将这些用在 Service、Controller 中的静态类和静态方法的引用,封装在普通 Bean 中,Service、Controller 使用这些 Bean 来完成相应的功能。这样一来,针对 Service、Controller 的单元测试中,就可以使用 @MockBean 结合 Mockito 直接 Mock 这些封装类及其方法了。

例如,在用户注册中,使用了 UUID 类来生成 用户id,使用 Date 插入注册时间,代码如下:

@Service
public class UsersServiceImpl implements UsersServiceInterface { @Autowired
private Users users; @Autowired
private UsersMapper usersMapper; /**
* 用户注册 service 方法
* @param userIn
* @return
*/
@Override
public String signUp(UserIn userIn) {
String result;
Date now = new Date();
users.setUserId(UUID.randomUUID().toString());
users.setRegTime(now);
...... try {
Integer result = usersMapper.insert(users);
if (0 == result) {
result = "fail";
} else {
result = "success";
} catch (Exception e) {
log.error(e.getLocalizedMessage(), e.fillInStackTrace());
result = "fail";
} finally {
return result;
}
}
}

对应的单元测试:

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringRunner.class)
@PowerMockIgnore({"javax.management.*", "javax.net.ssl.*"})
@PrepareForTest({UsersService.class, Date.class, UUID.class})
@SpringBootTest
@Transactional
public class UsersServiceMybatisImplTest { @Autowired
private UsersServiceMybatisImpl usersServiceMybatis; @MockBean
private EncryptInterface encryptInterface; @MockBean
private DateUtils dateUtils; @Autowired
private UsersMapper usersMapper; private UserIn userIn;
@Before
public void setUp() throws Exception {
userIn = new UserIn();
Mockito.when(encryptInterface.passwordGenerator("hello123")).thenReturn("abcdefghijklmn");
} @After
public void tearDown() throws Exception {
} @Test
public void signUp(){
Date date = (new GregorianCalendar(2018, 11, 9)).getTime();
PowerMockito.mockStatic(Date.class);
PowerMockito.whenNew(Date.class).withNoArgments().thenReturn(date);
String randomString = "abcdefg";
UUID uuid = PowerMockito.mock(UUID.class);
Mockito.when(uuid.toString()).thenReturn(randomString);
PowerMockito.mockStatic(UUID.class);
PowerMockito.when(UUID.randomUUID()).thenReturn(uuid);
userIn.setUserId("admin123");
userIn.setSign("盘古氏");
userIn.setEmail("pangu@gushen.com");
userIn.setPassword("hello123");
userIn.setRePassword("hello123");
userIn.setIp("127.0.0.1");
userIn.setNick("盘古");
userIn.setSchool("混沌大学");
assertEquals("success", result);
        Users user = usersMapper.selectByPrimaryKey("abcdefg");
assertEquals(date.toString(), user.getRegTime().toString());
......
} }

将静态类和静态方法封装成普通 Bean的示例如下:

工具类:

@Component
public class DateUtils {
public Date generateDate() {
return new Date();
}
}
@Component
public class UUIDUtils {
public Date generateUUID() {
return UUID.randomUUID();
}
}

Service 类:

@Service
public class UsersServiceImpl implements UsersServiceInterface { @Autowired
private Users users; @Autowired
private UsersMapper usersMapper; @Autowired
private DateUtils dateUtils; @Autowired
private UUIDUtils uuidUtils; /**
* 用户注册 service 方法
* @param userIn
* @return
*/
@Override
public String signUp(UserIn userIn) {
String result;
Date now = dateUtils.generateDate();
users.setUserId(uuidUtils.generateUUID().toString());
users.setRegTime(now);
...... try {
Integer result = usersMapper.insert(users);
if (0 == result) {
result = "fail";
} else {
result = "success";
} catch (Exception e) {
log.error(e.getLocalizedMessage(), e.fillInStackTrace());
result = "fail";
} finally {
return result;
}
}
}

单元测试:

@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class UsersServiceMybatisImplTest { @Autowired
private UsersServiceMybatisImpl usersServiceMybatis; @MockBean
private EncryptInterface encryptInterface; @MockBean
private DateUtils dateUtils; @MockBean
private UUIDUtils uuidUtils; @Autowired
private UsersMapper usersMapper; private UserIn userIn; @Before
public void setUp() throws Exception {
userIn = new UserIn();
Mockito.when(encryptInterface.passwordGenerator("hello123")).thenReturn("abcdefghijklmn");
} @After
public void tearDown() throws Exception {
} @Test
public void signUp(){
Date date = (new GregorianCalendar(2018, 11, 9)).getTime();
Mockito.when(dateUtils.generateDate()).thenReturn(date);
UUID uuid = Mockito.mock(UUID.randomUUID());
Mockito.when(uuid.toString()).thenReturn("abcdefg");
Mockito.when(uuidUtils.generateUUID()).thenReturn(uuid);
userIn.setUserId("admin123");
userIn.setSign("盘古氏");
userIn.setEmail("pangu@gushen.com");
userIn.setPassword("hello123");
userIn.setRePassword("hello123");
userIn.setIp("127.0.0.1");
userIn.setNick("盘古");
userIn.setSchool("混沌大学");
assertEquals("success", result);
Users user = usersMapper.selectByPrimaryKey("abcdefg");
assertEquals(date.toString(), user.getRegTime().toString());
......
}

最新文章

  1. FFT小总结
  2. PHP图片裁剪与缩放 / 无损裁剪图片
  3. jsp+servlet 中文乱码问题
  4. linux环境下安装mongodb
  5. ABAP--在查询条件只包含部分索引字段时,如何使用索引
  6. [Android Tips] 16. Update Android SDK from command-line
  7. css3颜色渐变
  8. 原生javascript实现ajax,post参数
  9. Are We There Yet? (zoj1745)
  10. html input密码显示为*号
  11. CentOS7从U盘中拷贝文件
  12. JS字符串和数组常用方法
  13. 头部banner根据网址高亮
  14. JSR286portlet中使用Ajax的方法
  15. Centos7安装并配置mysql5.6
  16. MQTT研究之EMQ:【JAVA代码构建X509证书】
  17. eclipse里面svn比较之前版本的代码
  18. python day11 ——1. 函数名的使⽤ 2. 闭包 3. 迭代器
  19. Python知识
  20. vs 调试 IE显示“无法显示该网页

热门文章

  1. Windows下搭建appium(Android版)
  2. 关于插入date型数据
  3. 图解Java常用数据结构(一)【转载】
  4. Java中的Filter
  5. 【c++】c++中重载输出操作符,为什么要返回引用
  6. swift中UITextView的使用
  7. 42-python中的矩阵、多维数组----numpy
  8. adf 笔记
  9. php初中高阶段
  10. codevs1246 丑数