Java单元测试技巧之PowerMock

简介: 高德的技术大佬向老师在谈论方法论时说到:“复杂的问题要简单化,简单的问题要深入化。” 这句话让我感触颇深,这何尝不是一套编写代码的方法——把阿里云域名续费优惠券一个复杂逻辑拆分为许多简单逻辑,然后把每一个简单逻辑进行深入实现,最后把这些简单逻辑整云服务器双11活动合为阿里云双十一优惠复杂逻辑,总结为八字真言即是“化繁为简,由简入繁”。

Java单元测试技巧之PowerMock

前言

高德的技术大佬向老师在谈论方法论时说到:“复杂的阿里云优惠购买问题要简单化,简单的问题要深入化。”
这句话让我感阿里云ecs续费优惠券触颇深,这何尝不是一套编写代码的方法——把一个复杂逻辑拆分为许多简单逻辑,然后把每一个简单逻辑进行深阿里云过了优惠期多少钱入实现,最后把这些简单逻辑整合为复杂逻辑,总结为八字真言即是“化繁为简,阿里云双十一活动拼团由简入繁”。
编写Java单元测试用例,其实就是把“复杂的问题要简单化”——即把一段复杂的代码拆解成一系列简单的单元测试用例;写好Java单元测试用例,其实就是把“简单的问题要深入化”——即学习一阿里双11现在交易额套方法阿里云双十一优惠、总结一套模式并应用到实践中。这里,作者根据日常的工作经验,阿里云服务器双11活动总结了一些Java单元测试技巧,以供大家交流和学习。

1. 准备环境

PowerMock是一个扩展了其它如Eas阿里云双十一活动老用户yMock等mock框架的、功能更加强大的框架。PowerMock使用一个自定义类加载器和字节码操作来模拟静态方法、构造方法、final类和方法、私有方法、去除静态初始化器双11活动阿里云的作用等等。

1.1. 引入PowerMock包

为了引入PowerMock包,需要在pom.xml文件中加入下列maven依赖:

Java单元测试技巧之PowerMock

1.2. 集成SpringMVC项目

在SpringMVC项目中,需要在pom.xml文件中加入JUnit阿里云双十一优惠的maven依赖:

Java单元测试技巧之PowerMock

1.3. 集阿里云成SpringBoot项目

在SpringBoot项目中,需要在pom阿里云双十一活动攻略.xml文件中加入JUnit的maven依赖:

Java单元测试技巧之PowerMock

1.4. 一个简单的测试用例

这里,用List举例,模拟一个不存在的列表,但是返回的列表大小为100。

public class L阿里云优惠istTest {
@Te阿里云双十一活动地址st
public void testSize() {
Int阿里云优惠卷eger expecte阿里双11现在交易额d = 100;
List list = PowerMockito.mock(List.class);
PowerMockito.when(list.size(阿里云双十一活动拼团)).thenReturn(expected);
Integer actual = list.size();
Assert.assertEquals("返回值不相等", expected, actual);
}
}

2. mock语句

2.1. mock方法

声明:
T PowerMockito.mock(Class clazz);
用途:
可以用于模拟指定类的对象实例。
当模拟非final类(接口、普通类、虚基类)的非final方法时,不必使用@RunWith和@PrepareForTest注解。当模拟final类或final方法时,必须使用@RunWith和@PrepareFor阿里会员日和双十一Tes阿里云优惠t注解。注解形如:
@RunWi阿里云双11优惠th(Pow阿里云服务器双十一特惠erMockRunner.class)
@PrepareForTest({TargetClass.class})

2.1.1. 模阿里云双十一活动拼团拟非final类普通方法

@Getter
@Setter
@ToString
public class Rectangle impleme阿里云双十一nts Sharp {
private double width;
private double height;
@Override
public double getArea() {
return width *阿里云几折优惠 height;
}
}
public class RectangleTest {
@Test
public void testGetArea() {
double expec阿里云服务器活动tArea = 100.阿里云双十一活动0D;
Rectangle rectangle = PowerMockito.mock(Rectangle.class)阿里云双11活动;
PowerMocki2019双11阿里销售额是多少to.when(rectangle.getArea()).thenReturn(expectArea);
double actualArea = r双11活动阿里云的作用ectangle.getArea();
Assert.assertEquals("返回值不相等", expectArea阿里云域名优惠券, actualArea, 1E-6D);
}
}

2.1.2. 模拟final类或final方法

@Getter
@Setter
@ToString
public final class Circle {
p阿里云双十一ri阿里云双11活动2020vate double radius;
public double阿里云双十一服务器 getArea() {
ret双11阿里云urn Math.PI * Math.pow(radius, 2);
}
}
@双11活动阿里云的作用RunWith(PowerMockRunner.class)
@PrepareForTest({Circle.class})
public class CircleTe阿里云和双十一有什么关系st {
@Test
public void testGetArea() {
double ex阿里云拼团活动pectArea阿里云代金券阿里云优惠券 = 3.14D;
Circle circle = PowerMockito.mock(Circle.class);
P阿里云双十一活动拼团owerMockit阿里巴巴拼团怎么拼o.when(circle.getArea(阿里云拼团)).thenR2019双11阿里销售额是多少eturn(expectArea);
double actu阿里云双11alArea = circle.getArea();
Assert.双11阿里云assertEquals("返回值不相等", ex阿里云服务器活动pectArea, actualArea, 1E-6D);
}
}

2.2. mo阿里云服务器活动ckStatic方法

声明:
PowerMockito.mockStatic(Class clazz);
用途:
可以用于模拟类的静态方法,必须使用“@RunWith”和“@PrepareFo阿里云服务器活动rTest”注解。

@RunWith(PowerMockRunner.class)
@PrepareFor阿里云过了优惠期多少钱Test阿里云双十一活动拼团({StringUtils.class})
public class StringUtilsTest {
@Test
pub推广阿里云双十一赚10万lic void testIs阿里云双十一活动老用户Empty() {
String string = "abc";
boolean expected = true;
PowerMockito.mo双11活动阿里云的作用ck阿里云双十一Static(StringUtils.class);
PowerMockito.when(StringUti阿里云新用户优惠券ls.isEmpty(string)).thenReturn(expected);
boolean actual =2018双11活动 Stri2018双11活动ngUtils.isEmpty(string);
Assert.assertEquals("返回值不相阿里云双十一活动拼团等", expected, actual);
}
}

3. spy语句

如果一个对象,我们只希望模阿里云双十一红包拟它的部分方法,而希望其它方法跟原来一样,可以使用Powe阿里云双十一rMockito.spy方双十一阿里云有优惠吗法代替PowerMockito.mock方法。于是,通过when语句阿里云设置过的方法,调用的是模拟方法;而没有通过when语句设置的方法,调用的是原有方法。

3.1. spy类

声明:
PowerMockito.spy(Class clazz);
用途:
用于模拟类的部分方法。
阿里云双十一活动拼团例:

public class Stri2019双11阿里销售额是多少ngUtils {
public static boolean isNot阿里云双十一活动Empty(阿里云双十一活动拼团final CharSequence cs) {
ret阿里双11现在交易额urn !isEmpty(cs);
}
public static boolean isEmp阿里巴巴双十一市场活动ty(final CharSeque双11活动阿里云的作用nce cs) {
return cs == null || cs.le阿里云双十一活动2018ngth() == 0;
}
}
@RunWith(PowerMockRunner.class)
@PrepareForTest({StringUtils.class})
public class StringUtilsTest {
@Test
public void testIsNotEmpty() {
St阿里云双十一活动ring string = null;
boolean ex阿里巴巴双十一市场活动pected = true;
PowerMockito.spy(StringUtils.class);
PowerMockito.when(StringUtils.isEmpty(string双11活动阿里云的作用)).thenReturn(!expected);
b阿里云服务器双11活动oolean actual = StringUtils.isNotEmp阿里云服务器双十一特惠ty(string);
As阿里云双11优惠sert阿里云双十一服务器.assertEquals("返回值不相等", expected, actual);
}
}

3.2. spy对象

声明:
T PowerMockito.spy(T object);
用途:
用于模拟对象的部分方法。
案例:

public class UserService {
private Long superUserId;
public boolean isNotSuperUser(Long use双十一阿里云有优惠吗rId) {
return !阿里云服务器优惠券isSuperUser(userId);
}
public boolean isSuperUser(Long userId) {
return Objects.阿里云双11优惠equals(userId, superUserId阿里双11数据);
}
}
@RunWith(PowerMoc阿里云优惠券kRunner.class)
public cl阿里云双十一活动拼团ass Use2019双11阿里销售额是多少rServiceTest {
@Test
public void testIsNotSuperUser() {
Long userId = 1L;
boolean expected = false;
UserS阿里云和双十一有什么关系ervice userService = PowerMockito阿里云域名续费优惠券.spy(new UserService());
PowerMockito.when(userService.isSuperUser(userId)).thenReturn(!expected);
boolean actual = userService.isNotSu阿里云双十一活动拼团perUser(userId);
Assert.assertEquals("返回值不相等", expected, actual);
}
}

4. when语句

4.1. when().thenReturn()阿里云双11活动模式

声明:

PowerMockito.when(mockObject.someMethod(someArgs)).thenReturn(expectedValue);
PowerMockit阿里双11数据o.when(mockObject.someMethod(someArgs)).thenThrow(expectedThrowable);
PowerMockito.when(mockObject.someMethod(so阿里云服务器活动meArgs))阿里云活动.thenA阿里云服务器双11活动nswer(阿里云双11活动2020expectedAn阿里双11数据swer);
PowerMockito.when(mockObje阿里云双十一活动拼团ct.someMethod(someArgs)).thenCallRealMethod();
用途:
用于模拟对象方法,先执行原始方法阿里双11数据,再返回期望的双11阿里云值、异常、应答,或阿里云双十一活动2018调用真实的方法。

4.1.1. 返回期望值

public class ListTest {
@T阿里云双十一红包est
public void testGet() {
int index = 0;
Integer expected = 100;
List<Integer> mockLi阿里云双十一红包st = PowerMockito.mock(List.class);
PowerMo阿里云优惠ck阿里云双十一活动拼团ito.when(mockList.get(index)).thenReturn(expected);阿里云服务器代金券领取
Integer actual = mockList.阿里云双11活动get(ind阿里云优惠服务器ex);
Assert.assertEquals("返回值不相等", expected, actual);
}
}

4.1.2. 返回期望异常

public class ListTest {
@Test(expected = IndexOutOfBoun阿里云优惠活动dsExc阿里云双11活动eption.class)
public void testGet() {
int index =阿里云双十一活动 -1;
Integer expected = 100;
List<Integer> mockList = PowerMockito.m阿里云服务器双11活动oc阿里云优惠卷k(List.class);
PowerMockito.when(mockList.get(index)).thenThrow(new IndexOutOfB阿里云双十一活动oundsException());
Integer actual = mockList.g云服务器双11活动et(index);
Assert.assertEquals("返回值不相等",阿里云双十一 expe阿里双11数据cted, actual);
}
}阿里云服务器拼团活动

4.1.3. 返回期望应答

pub双11阿里云lic class ListTest {
@Test
pu双11活动阿里云的作用blic void testGet() {
int index = 1;
Integer expected = 100;
List<Integer> mockList = PowerMockito.mock(List.class);
PowerMockito.when(mockList.get(index)).thenAnswer(invocation -> {
Integer value = invocation.getArgument(0);
return value * 100;阿里云优惠
});
Integer actual = mockList.get(index);
Assert.assertEquals("返回值不相等", expect阿里云双十一ed, actual);
}
}

4.1.4. 调用真实方法

public class ListTest {
@Test
pub阿里巴巴双十一市场活动lic阿里云新用户优惠券 void testGet() {
int ind2018双11活动ex = 0;
Integer expect阿里云双十一2020ed = 100;
List<Integer> oldList = new Arra阿里云双十一活动2018yL阿里云双11优惠ist<>();
oldList.add(expected);
List<Integer> spylist = PowerMockito.spy(oldList);
Powe阿里云服务器拼团rMockito.when(spylist.get(index)).thenCallRealMethod();
Integer actual = spylist.get(index);
Assert阿里云服务器双11活动.assertEquals("返回值不相等", expe阿里云双十一活动2018cted, actual);
}
}

4.2. doReturn()阿里云活动.when()模式

阿里云优惠口令明:
Po阿里云双11拼团wer阿里云双十一Mockito.doR云服务器双11活动eturn(expectedValue).when(mockObject).someMethod2018双11活动(someArgs);
PowerMockito.doThrow(expectedThrowable).whe阿里云领代金券n(mockObject).someM阿里云双11拼团ethod(someArgs);
PowerMockito.doAnswer(e阿里云续费优惠券xpectedAnswer).when(mockO阿里云双十一活动拼团bject).阿里云双十一活动someMeth阿里云双十一活动老用户od(someArgs);
PowerMockito.doNothing阿里云双十一活动拼团().when(mockObject).someMethod(someArgs);
PowerMockito.doCa阿里云域名续费优惠券llRealMe阿里会员日和双十一thod().when(mockObje阿里云双十一活动ct).someMethod(someArgs);
用途:阿里云双十一活动拼团
用于模拟对象方法,直接返回期望的值、异常、应答,或调用真实的方法,无需执行原始方法。
注意:
千万不要使用以下语法:
Powe阿里云双十一活动拼团rMockito.doReturn(expectedValue).when(mockObject.someMethod(someArgs));
PowerMockito.doThrow阿里云ecs续费优惠券(expectedThrowable).when(mockObject.someMethod(someArgs));
PowerMockito.doAnswer(expectedAnswer阿里云双11优惠).when(mockObject.someMethod(so阿里云双11活动2020meArgs阿里云拼团2019));
PowerMockito.doNothing().when(mockObject.someMet阿里云双十一活动2018hod(someArgs));
PowerMoc阿里云服务器双11活动kito.doCallRealMetho阿里云和双十一有什么关系d().when(mockObject.som云服务器优惠活动eMethod(someArgs));
虽然不会出现编译错误,但是在执行时会抛出UnfinishedStubbingException异常。

4.2.1. 返回期望值

public class List阿里云200元代金券Test {
@Test
pub阿里云优惠券最新领取lic void testGet() {
int index = 0;
Integer expected = 100;
List<Integer&gt阿里双十一数据; mockList阿里云双十一活动老用户 = PowerMockito.mock(List.class)阿里双11现在交易额;
PowerMockito.doReturn(exp云服务器双11活动ected).when(mockList).get(index);
Integer actual = mockList.get(阿里云双十一index);
Assert.assertEquals("返回值不相等", expected, actual);
}
}

4.2.2. 返回期阿里云双11活动望异常

public class ListTest {
@Tes阿里云双十一t(expected = IndexOutOfBoundsException.class)
public void testGet() {
int index = -1;
In阿里云双十一服务器teger expected = 100;
List<Integer> mockList = PowerMockito.mock(List.class);
PowerMockito.doThrow阿里云优惠(new IndexOutOfBoundsException()).when(mockList).get(index);
Integer actual = mockList.get(i阿里云服务器拼团活动ndex);
Assert.assertEquals("返回值不相等", exp阿里云代金券可以赠送吗ected, actual);
}
}

4.2.3.推广阿里云双十一赚10万 返回期望应答

public class ListTest {
@Test
public void testGet() {
int index = 1;
Integer expec阿里云优惠服务器ted = 100;
List<Integer> mockList = PowerMockito.moc阿里云优惠券怎么使用k(List.阿里云双11优惠券class);
P阿里云双十一owerMockito.doA阿里云服务器能干嘛nswer(invocation -> {
Intege阿里云双十一活动r value = invocation.getArgument(0);
return value * 100;
}).when(mockList).get(index);
Integer actual = mockList.get(ind阿里双11数据ex);
Assert.assertEqual阿里云双十一活动2018s("返回值不相等", expected, actua阿里云双十一活动l);
}
}

4.2.4. 模拟无返回值

public class ListTest {
@Test
public void testClear() {
List<Integer> mockList = PowerMockito.mock(List.class);
PowerMockito.doNothing().whe阿里云双十一n(mockList).clear();
mockList.clear();
Mo阿里云双十一ckito.verify(mockList).clear();
}
}

4.2.5. 调用真实方法

public class ListTest {
@Test
public void testGet() {
int index = 0;
Integer expected = 100;
List<I阿里云服务器能干嘛nteger> oldList = new ArrayList<&阿里云代金券怎么用gt;();
old阿里云双十一活动地址List.add(expected);
Li阿里云优惠券领取st<Integer> sp阿里云双十一2019ylist = PowerMockito.spy(oldList);
PowerMocki阿里云双十一2020to.doCallRealMethod().w阿里云双11hen(spylist).get阿里云双十一活动拼团(index);
Integer actual = sp阿里云和双十一有什么关系y阿里巴巴拼团怎么拼list.ge云服务器双11活动t(index);
Assert.assertEquals("返回值不相等", expected, actual);
}阿里云双11
}

4.3. 两种模式的主要区别

两种模阿里云优惠券领取式都用于模拟对象方法,在mock实例下使用时,基本上是没有差别的。但是,在spy实例下使用时,when()阿里云双十一活动拼团.thenReturn()模式会执行原方双11活动阿里云的作用法,而doReturn(阿里双11数据).when()模式不会执行原方法。阿里云双十一活动拼团
测试服务类:

@Slf4j
@Service
pub阿里云双十一2019lic class UserService {
public l阿里云双十一活动拼团ong getUserCount() {
log.info("调用获取用户数量方法");
return 0L;
}
}

使用when().thenReturn()模式:

@Ru阿里云双十一活动2018nWith(PowerMockRunner.class)
public class UserServiceTest {
@Test
public void testGetUserCount()阿里云双十一活动2018 {
Lon推广阿里云双十一赚10万g expected =阿里云双11老用户 1000L;
UserService use阿里云双十一活动拼团rService = PowerMockito.阿里云优惠码spy(new UserServ阿里云双十一活动老用户ice());
PowerMockito.when(userService.getUserCount()).thenReturn(expected);
Long actual = u双11阿里云serService.getUserCo阿里云优惠券怎么使用unt();
Assert.assertEquals("返回值不相等", expected, actual);
}
}

在测试过程中,将会打印出"调用获取用户数量方法"日志。

使用doReturn().when()模式:

@RunWith(阿里双11数据PowerMockRunner.class)
public class UserServiceTest {阿里云服务器拼团活动
@Test
publi阿里优酷拼团c void testGetUserCount() {
Long expected = 1000L;
UserService userService = PowerMockito.spy(new UserService());
PowerMockito.doReturn(expected).when(userService).getUserCount();
Long actual = userService.getUserCount();
Assert.assertEquals("返回值不相等", expected, actual);
}
}

在测试过程中,不会打印出"调用获取用户数量方法"日志。

4.4. whenNew模拟构造方法

声明:

PowerMockito.whenNew(MockClass.class).withNoArguments().thenReturn(expectedObject);
PowerMockito.阿里云双11优惠券whenNew(MockClass.class).withArguments(someArgs).thenReturn(expectedObj阿里巴巴双十一营销活动ect);
用途:
用于模拟构造方法。
案例:

public final class FileUtils {
public static bool阿里云双11ean isFile(String fileName) {
return new File(fileName).isFile();
}阿里云优惠卷
}
@RunWith(Powe阿里云双11活动rMock阿里双11数据Runner.class)
@PrepareForTest({FileUtils.cla阿里双11现在交易额ss})
public class FileUtilsTest {
@Test
public void testIsFile() throws Exception {
String fileName = "阿里双十一活动test.txt";
File file = PowerMockito.moc阿里云双十一k(File.class);
PowerMockito.whenNew(File.class).withArguments(fileName).thenReturn(file);
PowerMockito.when(file.isFile()).thenReturn(true);
Assert.as阿里云服务器活动sertTrue("返回值为假", FileUtils.isFile(fileName));
}
}

注意:需要加上注解@PrepareForTest(阿里双11数据{FileUtils.class}),否则模拟方法不生效。

5. 参数匹配器

在执行单元测试时,有时候并不关心传入的参数的值,可以使用参数匹配器。

5.1. 参数匹配器(any)

Mockito提供Mockito.anyInt()阿里巴巴双十一活动目的、M阿里云活动ockito.anyString、Mockito.any(Class clazz)等来表示任意值。

public class ListTest {
@Test
public void testGet() {
int index =阿里云优惠券怎么使用 1;
Integer expected = 100;
List<Integer> mockList = PowerMockito.mock(List.class);
PowerMockito.when(阿里云双十一活动攻略mockList.get(Mockito.anyInt())).thenReturn(expected);
Integer actual = mockList.get(index)阿里云双十一红包;
Assert.assertEquals("返回值不相等", expected, actual);
}
}

5.2. 参数匹配器(eq)

当我们使用参数匹阿里云双十一活动配器时,所有参数都应使用匹配器。 如果要为某一参数指定特定值时,就需要使用Mockito.eq()方法。

@RunWith(PowerMockRunner.class)
@Prepare阿里云优惠券ForTest({StringUtils.cla双11活动阿里云的作用ss})
public class StringUtilsTest {
@Te阿里云st
public voi2019双11阿里销售额是多少d testStartWith() {
String str阿里双11数据ing = "abc";阿里云活动
String prefix = "b";
bo阿里巴巴双十一活动目的olean expected = true阿里云双11活动;
Po阿里云双十一活动werMockito.spy(StringUtils.class);
Po阿里云双十一服务器werMockito.when(StringUtils.startsWith(Mockito.anyString(), Mockito.eq阿里云优惠活动(prefix))).thenReturn(expected);
boolean actual = StringUtils.startsWith(string, prefix);
Assert.assertEquals("返回值不相等", ex阿里双十一数据pected, actual);推广阿里云双十一赚10万
}
}

5.3. 附加匹配器

Mockito的Addi阿里云双十一活动tionalMatchers类提供了一些很少使用的参数匹配器,我们可以进行参数大于(gt)、小于(lt)阿里云双十一活动拼团、大于等于(geq)、小于等于(leq)等比较操作,也可以进行参数与(and)、或(or)、非(not)等逻辑计算等。

public cla阿里云双十一活动拼团ss ListTest {
@Test
public void testGet() {阿里云服务器双11活动
int ind阿里云双十一ex = 1;
Integer expected = 1阿里云双11优惠00;
List<Inte阿里双11数据ger> mockList = PowerMockito.mock(List.class);
PowerMocki阿里云双十一服务器to.when(mockList.get(AdditionalMatchers.geq(0))).thenReturn(阿里双11数据expected);
PowerMockito.when(mockList.get(AdditionalMatchers.lt(0))).thenT阿里云双11hrow(new IndexOutOfBoundsException());
Integer actual = mockList.get(index);
Assert.assertEquals("返回值不相等", expected, actual);
}
}

6. ver阿里云优惠ify语句

验证是确认在模拟过程中,被测试方法是否已按预期方式与其任何依推广阿里云双十一赚10万赖方法进行了交互。

格式:

Mockito.verify(mockObject[,times阿里双11现在交易额(int)]).someMethod(s阿里云双十一omgArgs);

用途:

用于模拟对象方法,直接返回期望的值、异常、应答,或调用真实的方法,无需执行原始方法。

案例:

6.1.云服务器双11活动 验证调用方法

public class ListTest {
@Test
public void test双11阿里云Get() {
List<Integer> mockList = Power阿里云代金券怎么用Mockito.mock(List.class);
Power阿里云服务器双11活动Mockito.doNothing().w阿里云双十一hen(mockList).clear();
mockList.clear();
Mockito.阿里云双11优惠verify(阿里云双十一卡住了吗mockList).clear();
}
}

6.2. 验证调用次数

public class ListTest阿里云服务器双11活动 {
@Test
public void testGet() {
List<Integer&g今年双十一京东与阿里t; mockList = PowerMockito.mock(List.class);
PowerMockito.doNothing().when(mockList).clear();
mockList.clear();
Mockito.verify(mockList, Mockito.times(1)).clear();
}
}

除t双11阿里云ime阿里云和双十一有什么关系s外,Mockito还支持atLeastOnce、atLeast、only、阿里云双11活动atMostOnce、atMost等次数验证器。阿里云优惠券领取

6.3. 验证阿里云活动调用顺序

public class ListTest {
@Test
public void testAdd() {
List<Integer> mockedList阿里云拼团服务器 = PowerMockito.mock(List.class);
PowerMockito.doReturn(true).when(mockedLi阿里云几折优惠st).add(Mockito.anyInt());
mockedList.add(1);
mockedList.add(2);
mockedList.add(3);
InOrder inOrder = Mockito.inOrder(mockedList);
inOrder.verify(mockedList).add(1);
i阿里云几折优惠nOrder.verify(mockedList).add(2);
inOrder.verify(mockedList).add(3);
}
}

6.4. 验证调用参数

public c阿里云双11活动lass ListTest {
@Test
public void testArgumentCaptor()阿里巴巴双十一活动目的 {
Integer[] expected阿里云双十一2020s = new Integer[] {1, 2, 3};
List<Integer> mockedList = P阿里云双十一活动2018owerMockito.mock(List.class);
PowerMockito.doRet阿里云urn(true).when(mocked阿里云优惠券List).add(Mockito.anyInt());
for阿里云双11拼团 (Integer expected : expecteds) {
mockedList.add(expected);
}
ArgumentC阿里云优惠活动aptor双11阿里云<Int2019双11阿里销售额是多少eger> argumentCapt阿里双11现在交易额or = ArgumentCaptor.forClass(I阿里云领代金券nteger.class);
Mockito.verify(mockedList, Mockito.times(3)).add(argumentCaptor.capture());
Integer[] actuals = argum云服务器双11活动entCaptor.getAllValues().toArray(new Integer[双11活动阿里云的作用0]);
Assert.assertArrayEquals("返回值不相2019双11阿里销售额是多少等", expecteds, actuals);
}
}

6.5. 确保验证完毕

Mockito提供Mockito.verifyNoMoreInteractions方法,在所有验证方法之后可以使用此方法,以确保所有调用都得到验证。如果模拟对象上存在任何未验证的调用,阿里云双11阿里云双十一2020会抛出NoInteractionsWanted异常。

public class2019双11阿里销售额是多少 ListTest {
@Test
public void testVerifyNoMoreInteractions() {
List&lt阿里云双十一活动时间;Integer> mockedList = PowerMockito.mock(List.class);
Mockito.verif阿里云拼团服务器yNoMoreInteractions(mockedList); // 执行正常
mockedList.isEmpty();
Moc阿里云双11kito.verifyNoMoreInteractions(mockedList); // 抛出异常
}
}

备注:Mockito.verifyZeroInteractions方法与Moc阿里双11现在交易额kito.verifyNo阿里云双十一MoreInteractions方法相同,但是目前已云服务器优惠活动经被废弃。

6.6. 验证静态方法

Mockito没有静态方法的阿里云优惠卷验证方法,但是PowerMock提供这方面的支持。

@RunWith(PowerMockRunner.class)
@PrepareForTest({StringUtils.class})
public class StringUtilsTest {
@Test
public void testVe阿里云代金券阿里云优惠券rifyStatic() {
Power推广阿里云双十一赚10万Mockito.mockStatic(StringUtils.class);
String expected = "abc";
StringUtils.isEmpty(expected);
PowerMockito.verifyStatic(StringUtils.clas阿里双11现在交易额s);
Argu阿里云双十一mentCaptor<String> argumentCaptor = Ar阿里云双十一2020gumentCaptor.forClass(String.class);
StringUtils.isEmpty(argumentCaptor.capture());
Asse双11活动阿里云的作用rt.assertEquals("参数不相等", argumentCaptor.云服务器双11活动getValue(), expected);
}
}

7. 私有属性

7.1. ReflectionTes阿里云双十一活动拼团tUtils.setField阿里云双十一方法

在用原生JUnit进行单元测试时,我们一般采用ReflectionTestUtils.setField方阿里云双十一活动老用户法设置私有属性值。

@S阿里双十一数据ervice
public class UserS云服务器双11活动ervice {
@Value("${system.userLimit}")
private Long userLimit;
public Long getUserLimit() {
return userLimit;
}
}
public class UserServiceTest {
@Autowired
priva阿里云优惠券te UserSe阿里云优惠券最新领取rvice userService;
@Test
public void testGetUserLimit() {
Long expected = 1000L;
Refle阿里巴巴双十一市场活动ctionTestUtils阿里云双十一红包.setField(user阿里云服务器双十一特惠Service, "user阿里云代金券可以赠送吗Limit", expected);
Long actual = userServic阿里云优惠券e.getUserLimit();
Assert.assertEquals("返回值不相等", expected, actual);
}
}

注意:在测阿里云服务器双11活动试类中,UserService实例是通过@Aut阿里云优惠owired注解加载的,如果该实例已经被动态代理,ReflectionTestUtils.setField方法设置的是代理实例,从而导致设置不生效。

7.2. Whitebox.setInternalState方法

现在使用PowerM阿里云双十一优惠ock进行单元测试时,可以采用Whitebox.setInterna阿里云服务器双11活动lState方法设置私有属性值。

@Ser阿里云拼团vice
public class UserService {
@Value("${system.userLimit}")
private Long userLimit;
public Long getUserLimit() {
return userLimit;
}
}
@RunWith(PowerMockRunner.class)
public class UserServiceTest {
@InjectMocks
private UserService userService;
@Test
public void testGetUserLimit() {
Long expe阿里云代金券领取cted = 1000L;
Whitebox.setInternalState(userService, "userLimit", expected);
Long actual双11阿里云 = userService.getUser阿里云双十一服务器Limit();
Assert.assertE阿里巴巴双十一市场活动quals("返回值不相等", expected, actual);
}
}

注意:需要加上注解@RunWith(PowerMockRunner.class)。

8. 私有方法

8.1. 模拟私有方法

8.1.1. 通过wh阿里云服务器双11活动en实现

public class UserService阿里双十一活动 {
private Long superUserId;
publi阿里云服务器拼团c boolean isNotSuperUser(Long userId) {
return !isSuperUser(use阿里云优惠rId);
}
private boolean isSuperUser(Long userId) {
return Objects.equals(userId, superUserId);
}
}
@RunWith(PowerMockRunner.class)
@PrepareForTest({UserService.class})
public class UserServiceTest {
@Test
public void testIsNotSuperUser() throws Exception {
Long use阿里云双十一活动拼团rId = 1L;
boolean expected = false;
UserService userService = PowerMockito.spy(阿里双十一活动new阿里云活动 UserService());
PowerMockito.when(userService, "isSuperUser", userId).thenReturn(!expe阿里云双十一卡住了吗cted);
boole阿里云服务器拼团活动an actual = userService.isNotSuperUser(userId);
Assert.assertEquals("返回值不相等", expected, actual);
}
}

8.1.2. 通过stub实现

通过模拟方法stub(存根),也可以实现模拟私有方法。但是,只能模拟整个方法的返回值,而不能模拟指定参数的返回值。

@RunWith(PowerMockRunner.class)
@PrepareFo阿里云域名续费优惠券rT阿里云新人优惠券est({UserServi阿里云和双十一有什么关系ce.class})
public class UserServiceTest {
@Test
public void testIsNotSuperUser() throws Exceptio阿里云双十一活动n {
L阿里云服务器双11活动ong userId = 1L;
boolean expected = false;
UserService userService = PowerMockito.spy(new UserService());
PowerMockito.s阿里云双十一活动2018tub阿里云双十一活动时间(PowerMockito.method(UserService.cla阿里云双11优惠ss, "isSuperUser", Long.c阿里云双十一活动2018lass)).toReturn(!ex阿里云双11优惠pected);
boolean阿里云 actual = userService.isNotSuperUser(userId);
Assert.assertEquals("返回值不相等", expected, actual;
}
}

8.3. 测试私有方法

@RunWith(PowerMockRunner.class)
public class UserServiceTest9 {
@T双11活动阿里云的作用est
public void testI阿里云优惠券领取sSuperUser() throws Exception {
Long userId = 1L;
boolean阿里云域名优惠券 expec阿里云双十一红包ted = false;
UserService userServ阿里云双十一2019ice = new UserService();
Method method = PowerMockito.method(UserService.clas阿里云优惠活动s, "isSupe阿里云服务器活动rUser", Lo阿里云双十一活动拼团ng.class);
Object actual = meth阿里云代金券od.invoke(userService, userId);
Assert.assertEqua今年双十一京东与阿里ls("返回值不相等", ex阿里云双十一活动拼团pec阿里云双十一2019ted, actual);
}
}

8.4. 验证私有方法

@RunWith(PowerMock阿里双11现在交易额Runner.class)
@PrepareForTest({UserService.class})
public class User阿里云双11活动ServiceTest10 {
@Test
public void testIsNo阿里云tSuperUser() throws Exception {
Long userId = 1L;
bool2019双11阿里销售额是多少ean expected = false;
UserService userService = PowerMockito.spy(new UserService());
PowerMockito.when(userService, "isSuperUser", userId).thenReturn(!expected);
boolean actual = userSer阿里云双十一2019vice.i阿里云活动sNot阿里云拼团服务器SuperUser(userId);
PowerMocki今年双十一京东与阿里to.verifyPrivate(userService).invoke("isSuperUser", userId);
Assert.assertEquals("返回值不相2019双11阿里销售额是多少等", expected, actua阿里云双十一2019l);
}
}

这里,也可以用Method那套方法进行模拟和验证方法。

9. 主要注解

PowerMock为了更阿里云新用户域名代金券好地支持SpringMVC/SpringBoot项目,提供了一系列的注解,大大地简化了测试代码。

9.1. @RunWith注解阿里云双十一卡住了吗

@RunWith(PowerMockRunner.class)

指定JUnit 使用 PowerMock 框架中的单元测试运行器。

9.2. @PrepareForTest注解

@Prep阿里云双十一活动拼团areForT阿里云双11优惠est({ TargetClass.class })

当需要模拟fi阿里云双11活动nal类、final方法或静态阿里云双十一活动拼团方法时,需要添加@PrepareForTest注解,并指定方法所在的类。如果需要指定多个类,在{}中添加多个类并用逗号隔开即可。

9.3. @Mock注解

@Mock注解创建了一个全部Mock的实例,所有属性和方法全被置空(0或者null)。阿里云和双十一有什么关系

9.4. @Spy注解

@Spy注阿里云过了优惠期多少钱解创建了一个没有Mock的实例,所有阿里云双11活动成员方法都会按照原方法的逻辑执行,直到被Mock返回某个具体的值为止。

注意:@Spy注解的变量需要被初始化,否则执行时会抛出异常。

9.5.阿里云双十一 @InjectMocks注解

@InjectMocks注解创建阿里双十一活动一个实例,阿里云服务器活动这个实例可以调用真实代码的方法,其余用@Moc阿里云域名续费优惠券k或@Spy注解创建的实例将被注入到用该实例中阿里云优惠券

@Service
public class UserService {
@Autowired
private UserD阿里云双11老用户AO userDAO;
public void modifyUser(Us双11活动阿里云的作用erVO userVO) {
UserDO userDO = new UserDO();
Be阿里云双11活动anUtils.copyProperties(userVO, user阿里云DO);
userDAO.modify(userDO);
}
}
@R阿里云服务器双11活动unWith(Power阿里云双十一2019MockRunner.class2019双11阿里销售额是多少)
public class UserServiceTest {
@Mock
private Use阿里云优惠券rDAO userDAO;
@Inj双十一阿里云有优惠吗ectMocks
private UserService userService;
@双11阿里云Test
public void tes阿里云优惠券最新领取tCreateUser() {
UserVO u阿里云双十一serVO = new UserVO();
userVO.setId(1L);
userVO.setName(阿里云双十一活动"changyi");
userVO.setDesc("test user");
userService.modifyUser(userVO);
ArgumentCaptor<UserDO&2019双11阿里销售额是多少gt; argumentCa阿里云优惠口令ptor = ArgumentCaptor.forClass(UserDO.cl阿里云双十一活动2018ass);
Mockito.verify(userDAO).modify(argumentCaptor.capture());
UserDO userDO = argumentCaptor.getValue();
Assert阿里双11现在交易额.assertNotNull("用户实例为空", userDO);
Assert.assertEqu阿里巴巴双十一有优惠吗als("用户标识不相等", userVO.getId(), us阿里云服务器双11活动erDO.getId());
Assert.assertEquals("用户双11阿里云名称不相等", userVO.getName(), userDO.getNam阿里云续费优惠券e());
Assert.as阿里云双11活动sertEquals("阿里云服务器拼团活动用户描述不相等", userVO.getDesc(), userDO.getDesc());
}
}

9.6. @Captor注解

@Captor注解在字段级别创建参数捕获器。但是,在测试方法启动前,必须调用MockitoAnnotations.openMocks(this)进行初始阿里云双十一活动化。

@Servi阿里双11现在交易额ce
public class UserServic双十一阿里云有优惠吗e {
@Autowired
private UserDAO userDAO;
public void modi阿里云服务器优惠券fyUser(User阿里双11现在交易额VO userVO) {
UserDO userDO = new UserDO();
BeanUtils.c阿里云双十一2020opyProperties(userVO, userDO);
userDAO.modify(userDO);
}
}
@RunWith(PowerMockRunner.class阿里双11现在交易额)
publi阿里巴巴双十一市场活动c c阿里云活动lass UserServiceTest {
@M阿里云优惠ock
private UserDAO use阿里云双十一活动拼团rDAO;
@Injec阿里云服务器双11活动tMocks
pr阿里云双十一ivate UserService userService;
@Captor
p阿里云服务器双十一特惠rivate ArgumentCa阿里云和你拼了ptor<UserDO> argumentCaptor;
@Before
public void beforeTest() {
MockitoAnnotations.openMocks(this);
}
@Test
public void t阿里云优惠口令estCreateUser() {
UserVO userVO = new UserV阿里双11现在交易额O();
userVO.setId(1L);
userVO.setName("changyi");
userVO.setDesc("test user");
userService.modifyUser(userVO);
Mockito.verify(userDAO).modify(argumen阿里云双十一活动时间tCaptor.capture());
UserDO userDO = argumentCaptor.getValue();
Assert.assertNotNull("用户实例为空", userDO);
Assert.assertEquals("用户标识不相等阿里云双十一", userVO.getId(), userDO.getId());
Assert.assertEqual推广阿里云双十一赚10万s(阿里云和双十一有什么关系"用户名称不相等", userVO.getName(), userD阿里云服务器活动O.getName());
Assert.ass阿里云双11活动ertEquals("用户描述不相等", userVO.getDesc(), userDO.ge阿里云双11活动tDesc());
}
}

9.7. @PowerMockIgnore注解

为了解决推广阿里云双十一赚10万使用PowerMock后,提示ClassLoader错误。

10. 相关观点

10.1. 《Java开发手册》阿里云优惠券领取规范

【强制】好的单元测试必须遵守AIR原则。 说明:单元测试在线上运行时,感觉像空气(AIR)一阿里云双十一活动攻略样感觉不到,但在测试质量的保障上,却是非常关键的。好的单元测试宏观上来说,具有自动化、独立性、可重复执行的特点。

A:Automatic(自阿里云双十一活动地址动化)

I:I阿里云新用户域名代金券ndependent(独立性阿里云双11优惠

R:Repeatable(可重复)

【强制】单元阿里云双11活动测试应该是全自动执行的,并且非交互式的。测试用例通常是被定期执行的,执行过程必须完全自动化才有意义。输出结果需要人工检查的测试不是一个好的单元测试。单元测试中不准使用System.阿里云优惠码out来进行人肉验证,必阿里云双十一活动2018须使用asser阿里云双11优惠t来验证。

【强制】单元测试是可以重复执行的,不能受到外界环境的影响。

说明:单元测试通常会被放到持阿里云优惠券最新领取续集成中,每次有代码check in时单元测试都会被执行。如果单测对外部环境(网络、服务、阿里云服务器双11活动中间件等)有依赖,容易导致持续集成阿里云双十一红包机制的不阿里云双十一活动可用。

阿里双11现在交易额例:为了不受外界环境影响,要求设计代码时就把SUT的依赖改成注入,在推广阿里云双十一赚10万测试时用spring 这样的DI框架注入阿里云领代金券一个本地(内存)实现或者Mock实现。

【推荐】编写单元测阿里云和双十一有什么关系试代码阿里云双十一活动拼团遵守BCDE原则,以保证被测试模块阿里云优惠服务器的交付质量。

B:Border,边界值测试,包括循环边界、特殊取值、特殊时间点、数据顺序等。

C:Correct,正确的输入,并得到预期的结果。

D:Design,与设计文档相结合,来编写单元测试。

E:Error,强制错误信息输入(如:非法数据、异常流程、业务允许外等),并得到预期的结果。

10.2. 为什么要使用Mock?

根据网络相关资料,总结观点如下:

Mock可以用来解除外部服务依赖,从而保证了测试用例的独立性。

现在的互联网软件双11活动阿里云的作用系统,通常采用了分布式部署的微服务,为了单元测试某一服务而准备其它服务,存在极大阿里云双十一活动2018的依耐性和不可行性。

Mock可以减少全链路测试数据准备,从而提高了编写测试用例的速度。

传统的集成测试,需要准备全链路的测试数据,可能某些环节并不是你所熟悉的。最后,耗费了大量的时间和经历,并不一定得到你想要的结果。现在的单元测试,只需要模拟上游的输入数据,并验阿里云双11活动证给下游的输出数据,编写测试用2018双11活动例并进行测试的阿里云活动速度可以提高阿里巴巴双十一活动目的很多倍。

Mock可以模拟一些非正常的流程,从而保证了测试用例的代码覆盖率阿里云双十一2019

根据单元测试的BCDE原则,需要进行边界值测阿里云服务器双11活动试(Border)和强制错误信息输入(Error),这样阿里云拼团2019有助于覆盖整个代码逻辑。在实际系统中,很难去构造这些边界值,也能难去触发这些错误信息。而Mock从根本2019双11阿里销售额是多少上解决了这个问题:想要什么样的边界值,只需要进行Mock;想要什么样的错误信息,也只需要进行Mock。

Mock可以不用加载项目环境配置,从而保证了测试用例的执行速度。

在进行集成测试时,我们需要加载项目的所有环境配置,启动项目依赖的所有服务接口。往往执行一个测试用例,需要几分钟乃至几十分钟。采用Mock实现的测试用例,不用加载项目环境配置,也不依赖其它服务接口,执行速度往往在几秒之内,大大地提高阿里云双十一活动老用户了单元测试的执行速度双11阿里云

10.3. 单元测试与集成测试的区别

在实际工作中,不少同学用集成测试代替了单元阿里云双十一活动拼团测试,或者认为集成测试就是单元测试。这里,总结为了单元测试与集成测试的区别:

测试对象不同
单元测试对象是实现了具体功能的程序单元,集成测试对象是概要设计规划中的模阿里云拼团块及模块间的组合双11活动阿里云的作用

测试方法不同
单元测试中的主要方法是基于代码的白盒测试,集成测试中主要使用基于功能的黑盒测阿里云双11优惠试。

测试时间不同
集成测试要晚于单元测试。

测试内容不同
单元测试主要是模块内程序的逻辑、功能、参数传递、变量引用、出错处理及需求和设计中具体要求方面的测试;而集成测试主要验证各个接口、接口之间的数据传递关系,及模块组合后能否达到预期效果

作者:开发者小助手_LS