jMockit中文网备份 @Test&@Injectable
Posted funkboy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jMockit中文网备份 @Test&@Injectable相关的知识,希望对你有一定的参考价值。
-
@Injectable 与 @Mocked的不同
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
//@Mocked与@Injectable的不同 public class MockedAndInjectable { @Test public void testMocked( @Mocked Locale locale) { // 静态方法不起作用了,返回了null Assert.assertTrue(Locale.getDefault() == null ); // 非静态方法(返回类型为String)也不起作用了,返回了null Assert.assertTrue(locale.getCountry() == null ); // 自已new一个,也同样如此,方法都被mock了 Locale chinaLocale = new Locale( "zh" , "CN" ); Assert.assertTrue(chinaLocale.getCountry() == null ); } @Test public void testInjectable( @Injectable Locale locale) { // 静态方法不mock Assert.assertTrue(Locale.getDefault() != null ); // 非静态方法(返回类型为String)也不起作用了,返回了null,但仅仅限于locale这个对象 Assert.assertTrue(locale.getCountry() == null ); // 自已new一个,并不受影响 Locale chinaLocale = new Locale( "zh" , "CN" ); Assert.assertTrue(chinaLocale.getCountry().equals( "CN" )); } } |
@Injectable 也是告诉 JMockit生成一个Mocked对象,但@Injectable只是针对其修饰的实例,而@Mocked是针对其修饰类的所有实例。
此外,@Injectable对类的静态方法,构造函数没有影响。因为它只影响某一个实例嘛!
-
@Tested & @Injectable 两个好基友,通常搭配使用
为便于演示,我们以电商网站下订单的场景为例:在买家下订单时,电商网站后台程序需要校验买家的身份(是否合法,例如是否在黑名单中),
若下订单没有问题还要发邮件给买家。 相信下面的代码,你一定能看明白 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// 邮件服务类,用于发邮件 public interface MailService { /** * 发送邮件 * * @param userId * 邮件接受人id * @param content * 邮件内容 * @return 发送成功了,就返回true,否则返回false */ public boolean sendMail( long userId, String content); } |
1
2
3
4
5
6
7
8
9
10
11
12
|
// 用户身份校验 public interface UserCheckService { /** * 校验某个用户是否是合法用户 * * @param userId * 用户ID * @return 合法的就返回true,否则返回false */ public boolean check( long userId); } //订单服务类 ,用于下订单 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
public class OrderService { // 邮件服务类,用于向某用户发邮件。 MailService mailService; // 用户身份校验类,用于校验某个用户是不是合法用户 @Resource UserCheckService userCheckService; // 构造函数 public OrderService(MailService mailService) { this .mailService = mailService; } /** * 下订单 * * @param buyerId * 买家ID * @param itemId * 商品id * @return 返回 下订单是否成功 */ public boolean submitOrder( long buyerId, long itemId) { // 先校验用户身份 if (!userCheckService.check(buyerId)) { // 用户身份不合法 return false ; } // 下单逻辑代码, // 省略... // 下单完成,给买家发邮件 if (! this .mailService.sendMail(buyerId, "下单成功" )) { // 邮件发送成功 return false ; } return true ; } } |
假设现在我们需要测试OrderService类的submitOrder方法,可是OrderService依赖MailService,UserCheckService类,
在测试过程中,我们并不想真正连结邮件服务器,也不想连结校验用户身份的服务器校验用户身份,怎么办呢?
此时@Tested与@Injectable就排上用场了!请看下面的测试程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
//@Tested与@Injectable搭配使用 public class TestedAndInjectable { //@Tested修饰的类,表示是我们要测试对象,在这里表示,我想测试订单服务类。JMockit也会帮我们实例化这个测试对象 @Tested OrderService orderService; //测试用户ID long testUserId = 123456l; //测试商品id long testItemId = 456789l; // 测试注入方式 @Test public void testSubmitOrder( @Injectable MailService mailService, @Injectable UserCheckService userCheckService) { new Expectations() { { // 当向testUserId发邮件时,假设都发成功了 mailService.sendMail(testUserId, anyString); result = true ; // 当检验testUserId的身份时,假设该用户都是合法的 userCheckService.check(testUserId); result = true ; } }; // JMockit帮我们实例化了mailService了,并通过OrderService的构造函数,注入到orderService对象中。 //JMockit帮我们实例化了userCheckService了,并通过OrderService的属性,注入到orderService对象中。 Assert.assertTrue(orderService.submitOrder(testUserId, testItemId)); } } |
-
@Tested & @Injectable功能总结
@Injectable 也表示一个Mocked对象,相比@Mocked,只不过只影响类的一个实例。而@Mocked默认是影响类的所有实例。
@Tested表示被测试对象。如果该对象没有赋值,JMockit会去实例化它,若@Tested的构造函数有参数,
则JMockit通过在测试属性&测试参数中查找@Injectable修饰的Mocked对象注入@Tested对象的构造函数来实例化,
不然,则用无参构造函数来实例化。除了构造函数的注入,JMockit还会通过属性查找的方式,把@Injectable对象注入到@Tested对象中。
注入的匹配规则:先类型,再名称(构造函数参数名,类的属性名)。若找到多个可以注入的@Injectable,则选择最优先定义的@Injectable对象。
当然,我们的测试程序要尽量避免这种情况出现。因为给哪个测试属性/测试参数加@Injectable,是人为控制的。 -
什么测试场景,我们要使用@Tested & @Injectable
显然,当我们需要手工管理被测试类的依赖时,就需要用到@Tested & @Injectable。
两者搭配起来用,JMockit就能帮我们轻松搞定被测试类及其依赖注入细节。
以上是关于jMockit中文网备份 @Test&@Injectable的主要内容,如果未能解决你的问题,请参考以下文章