后续为了提升研发效率,解决项目中新引入代码的质量问题,开发必须采用单元测试的方式对自身实现的方法进行测试。保证验证通过。在单元测试中,为了解决spring的依赖问题,我们选用Mockito作为Mock测试框架。
首先需要了解一些基本概念:
- 什么是Mocking
Mocking is a way to test the functionality of a class in isolation.
Mocking不要求例如数据库连接,文件系统等工程启动时的初始化信息。只专注于测试某个方法内部逻辑。我们之前做一些service的测试,可能需要先加载spring的各种配置,连接好各种中间件等。这种重量级的测试对我们的单元测试非常不友好,而且容易导致脏数据的产生。针对于这些问题,我们使用mocking,对某些外部依赖的服务,类等,使用预先设置的值,而不是真实的加载他们。从而使得单元测试成为一个轻量级的过程。
- Mockito框架
Mockito就是用来进行mocking的框架。具体介绍请参考 https://github.com/mockito/mockito
- PowerMockito框架
Mockito不能针对static方法进行mock,但程序中很多地方使用了static的方法。为了解决这一问题,我们引入PowerMockito框架。
- Mockito,PowerMockito引入
Mockito maven依赖:http://mvnrepository.com/artifact/org.mockito/mockito-all
最新稳定版本为1.10.19
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>
配合Junit食用效果更佳
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>2.2.0</version>
<scope>test</scope>
</dependency>
PowerMockito maven依赖:
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>1.6.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>1.6.2</version>
<scope>test</scope>
</dependency>
- 使用说明
参考教程
1:Mockito https://www.tutorialspoint.com/mockito/index.htm
2.PowerMockito https://github.com/powermock/powermock/wiki/MockitoUsage
mockito框架创建mock对象不能对final,static,Anonymous,primitive类进行mock。 PowerMockito框架可以对final static方法进行mock。
贴一段写的针对于模拟支付链接生成的代码作为案例讲述。
/**
* @author Huang, Liangliang
*
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({OPOuterApiConfig.class,OPOrderManageConfig.class})
public class ChargeTest {
@InjectMocks
private BossService bossService;
@Mock
private UserManageService userManageService;
@Mock
private JournalAccountService journalAccountService;
private static Logger log = LoggerFactory.getLogger(ChargeTest.class);
@Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
PowerMockito.mockStatic(OPOuterApiConfig.class);
PowerMockito.mockStatic(OPOrderManageConfig.class);
PowerMockito.when(OPOrderManageConfig.getTestValue()).thenReturn(new Boolean(false));
when(OPOrderManageConfig.getBossVmOsAvailableName()).thenReturn("linux,windows");
// when(OPOrderManageConfig.getTestValue()).thenReturn(new Boolean(true));
when(journalAccountService.journalCharge(userId,36480)).thenReturn(Utils.getUUID());
Customer customer=new Customer();
customer.setBossId("something");
}
@Test
public void chargeTest() throws Exception {
String notifyUrl=someurl;
String returnUrl=someurl;
String resource=bossService.generateChargeUrl(userId, 36480, ProductConstants.Order.ORDER_SOURCE_OP, notifyUrl, returnUrl);
Mockito.verify(journalAccountService,Mockito.times(0)).getWithdraw("");
log.info(resource);
log.info("Test value:{}",OPOrderManageConfig.getTestValue());
}
}
@RunWith(PowerMockRunner.class)标签: 当需要mock静态方法的时候,必须加注解@PrepareForTest和@RunWith。注解@PrepareForTest里写的类是静态方法所在的类。由PowerMockito提供。
当不需要对static final方法进行mock时,使用mockito提供的标签即可。 @RunWith(MockitoJUnitRunner.class)
@InjectMocks, @Mock标签
@Mock标签等同于Mockito.mock(classToMock);用来初始化一个mock对象。@InjectMocks 标签标注的类可以通过反射使用@Mock标签标注的类(自动注入)。当代码使用spring的标签,想要初始化mock类时,采用@InjectMocks, @Mock标签更为方便(不需要实现get set方法)。
MockitoAnnotations.initMocks(this);
初始化Mock标签
PowerMockito.mockStatic(OPOuterApiConfig.class);
Call PowerMockito.mockStatic() to mock a static class (use PowerMockito.spy(class) to mock a specific method):
when(OPOrderManageConfig.getBossVmOsAvailableName()).thenReturn(“linux,windows”);
Mockito的条件注入,指定mock类在什么情况下,返回什么值。
Mockito.verify(journalAccountService,Mockito.times(0)).getWithdraw(“”);
verify:Verify that certain methods from the mock object are called.用来验证这个方法是否被调用到。可以指定次数。