单元测试框架入门

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一、Mockito的使用
哔哩哔哩 - ( ゜- ゜)つロ 乾杯~ - bilibili
Mockito介绍
Mockito 是一个强大的用于 Java 开发的模拟测试框架, 通过 Mockito 我们可以创建和配置 Mock 对象, 进 而简化有外部依赖的类的测试。一个典型的场景就是实现同数据库dao解耦。 使用 Mockito 的大致流程如下: 创建外部依赖的 Mock 对象, 然后将此 Mock 对象注入到测试类中. 执行测试代码. 校验测试代码是否执行正确.
哔哩哔哩 - ( ゜- ゜)つロ 乾杯~ - bilibili
各种any方法
Matchers.anyString()表示匹配任意字符串。 Matchers.anyInt()匹配任意int类型参数。 Matchers.isA(Class<T> clazz)匹配特定类型。
/** * 匹配任意字符串 */
@Mock private MyService mockService; @Test public void testFinalMethod() {//mock Final方法
Mockito.when(mockService.getFinaleValue()).thenReturn("modify"); Assert.assertEquals("modify", mockService.getFinaleValue()); }
@Test public void anyStringTest() {
when(queryDao.queryByKey(anyString())).thenReturn("1"); assertEquals("1", myService.queryByKey("1")); assertEquals("1", myService.queryByKey("2")); } /** * 根据自定义类型匹配 */ @Test public void anyClassTest() { when(queryDao.queryByDto(isA(MyDto.class))).thenReturn("123"); MyDto myDto = new MyDto(); assertEquals("123", myService.queryByDto(myDto)); }
哔哩哔哩 - ( ゜- ゜)つロ 乾杯~ - bilibili
Mockito原理
Mockito通过代理拦截实现模拟。下面通过一个例子直观的展示。
哔哩哔哩 - ( ゜- ゜)つロ 乾杯~ - bilibili
基于注解的启动
@RunWith(MockitoJUnitRunner.class) 以Mockito启动器启动,加载上下文。 @Mock注解创建一个模拟对象,通常是dao与业务Service中第三方Service。 @InjectMocks 把mock对象注入要测试的类,同时会调用测试类的构造函数初始化。
}
/** * PowerMock处理特殊测试用例 */
@RunWith(PowerMockRunner.class) //以PowerMock启动Junit test @PrepareForTest({MyService.class}) //预处理要mock的类,在字节码的级别更改类的行为 public class PowerMockTest {
单元测试框架分享
夏佳佳
2019.04.25
哔哩哔哩 - ( ゜- ゜)つロ 乾杯~ - bilibili
一、Mockito的使用 二、PowerMock的使用 三、Maven Test的配置与使用 四、不当的单元测试用例 五、PPT中的单元测试示例源码
哔哩哔哩 - ( ゜- ゜)つロ 乾杯~ - bilibili
return true; } return false; } } ) )).thenReturn("霜剑");
assertEquals("桑田", myService.queryByKey("沧海")); assertEquals("霜剑", myService.queryByKey("风刀"));
哔哩哔哩 - ( ゜- ゜)つロ 乾杯~ - bilibili
处理final方法
通过RunWith(PowerMockRunner.class) 加装PowerMock启动器。用法同Mockito。
public final String getFinaleValue() { return "final";
哔哩哔哩 - ( ゜- ゜)つロ 乾杯~ - bilibili
处理静态方法
通过RunWith(PowerMockRunner.class) 加装PowerMock启动器 @PrepareForTest({MyService.class}) 预处理要mock的类 PowerMockito.mockStatic处理静态类,剩下的步骤同Mockito,通过when thenReturn模拟。
}
哔哩哔哩 - ( ゜- ゜)つロ 乾杯~ - bilibili
处理new方法
PowerMockito.whenNew 结合withNoArguments() 模拟无参构造方法。 withParameterTypes 跟 withArguments 模拟带参构造方法
@Test public void mockNew() throws Exception {//模拟不带参数的New构造方法
} ) )).thenReturn("桑田"); when(queryDao.queryByKey(Mockito.argThat(new ArgumentMatcher<String>() {
@Override public boolean matches(Object argument) {
String arg = (String) argument; if ("风刀".equals(arg)) {
String expectKey = "order_key"; Mockito.doNothing().when(queryDao).updateByKey(argument.capture()); myService.updateByKey2("key"); // 验证内部关键方法执行一次 Mockito.verify(queryDao, Mockito.times(1)).updateByKey(expectKey); // 验证参数为expectKey Assert.assertEquals(expectKey, argument.getValue()); }
/** * PowerMock处理特殊测试用例 */
@RunWith(PowerMockRunner.class) //以PowerMock启动Junit test @PrepareForTest({MyService.class}) //预处理要mock的类,在字节码的级别更改类的行为 public class PowerMockTest {
when(...).thenReturn(...) 方法链可以指定多个返回值, 当这样做后, 如果多次调用指定的方法, 那么这个方 法会依次返回这些值. 例如 "when(i.next()).thenReturn("Hello“,”world”) 这句代码表示: 第一次调用 i.next() 时返回 "Hello,", 第二次调用 i.next() 时返回 " world ".
哔哩哔哩 - ( ゜- ゜)つロ 乾杯~ - bilibili
抓取参数
某个方法没有返回值,除了验证内部关键方法,还可以抓取内部参数来验证逻辑。
/** * 声明参数抓取 */
@Captor private ArgumentCaptor<String> argument;
/** * 抓取参数 */
@Test public void argumentCaptorTest() {
queryDao.updateByKey(key+"2"); }
/** * 验证方法调用次数 */
@Test public void verifyTest() {
Mockito.doNothing().when(queryDao).updateByKey("key"); myService.updateByKey("key"); Mockito.verify(queryDao, Mockito.times(2)).updateByKey("key"); }
}
哔哩哔哩 - ( ゜- ゜)つロ 乾杯~ - bilibili
verify验证方法
有些场景需要验证方法是否调用,比如某个方法没有返回值,通过验证内部关键方法来验证逻辑。 Mockito.times表示方法期望执行的次数。
public void updateByKey(String key) { //业务组装 queryDao.updateByKey(key);
哔哩哔哩 - ( ゜- ゜)つロ 乾杯~ - bilibili
ห้องสมุดไป่ตู้
参数匹配
when(...).thenReturn(...) 方法链可以指定多个返回值, 但欠缺灵活。
ArgumentMatcher提供了根据参数进行条件返回的功能。这里有一个限制就是,如果在调用方法时需要
传入多个参数,其中一个参数使用了argument matcher,那么所有的参数必须都是matcher类型。
Mockito.when(mockService.getParentMessage()).thenReturn("test8899"); PowerMockito.whenNew(MyService.class).withNoArguments().thenReturn(mockService); MyService testNew = new MyService(); Assert.assertEquals("test8899", testNew.getParentMessage()); }
哔哩哔哩 - ( ゜- ゜)つロ 乾杯~ - bilibili
二、PowerMock的使用
哔哩哔哩 - ( ゜- ゜)つロ 乾杯~ - bilibili
Mockito的局限
Mockito无法处理静态方法,构造函数,final类等特殊用例。 PowerMock是一个扩展了Mockito框架的、功能更加强大的框架。 PowerMock使用一个自定义类加载器和字节码操作来模拟静态方法,构造函数, final类和方法,私有方法,去除静态初始化器等等。 注意只有遇到Mockito无法处理的场景再使用PowerMock。
@Mock private MyService mockService;
@Test public void testStaticMethod() {//mock静态方法
PowerMockito.mockStatic(MyService.class); Mockito.when(MyService.getMessage()).thenReturn("world"); Assert.assertEquals("world", MyService.getMessage()); }}
如下通过argument matcher条件返回
/** * 参数匹配 */
@Test public void returnByMatcher() {
when(queryDao.queryByKey(Mockito.argThat(new ArgumentMatcher<String>() { @Override public boolean matches(Object argument) { String arg = (String) argument; if ("沧海".equals(arg)) { return true; } return false; }
哔哩哔哩 - ( ゜- ゜)つロ 乾杯~ - bilibili
when-thenReturn
when(...).thenReturn(...) 方法链来定义一个行为, 例如 "when(mockedList.add("one")).thenReturn(true)" 表示: 当调用了mockedList.add(“one”), 那么返回 true。并且要注意的是, when(...).thenReturn(...) 方法 链不仅仅要匹配方法的调用, 而且要方法的参数一样才行.
相关文档
最新文档