jMockit中文网备份 @Test&@Injectable

    1. @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对类的静态方法,构造函数没有影响。因为它只影响某一个实例嘛!

    1. @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));

    }

}

  1. @Tested & @Injectable功能总结

    @Injectable 也表示一个Mocked对象,相比@Mocked,只不过只影响类的一个实例。而@Mocked默认是影响类的所有实例。
    @Tested表示被测试对象。如果该对象没有赋值,JMockit会去实例化它,若@Tested的构造函数有参数,
    则JMockit通过在测试属性&测试参数中查找@Injectable修饰的Mocked对象注入@Tested对象的构造函数来实例化,
    不然,则用无参构造函数来实例化。除了构造函数的注入,JMockit还会通过属性查找的方式,把@Injectable对象注入到@Tested对象中。
     注入的匹配规则:先类型,再名称(构造函数参数名,类的属性名)。若找到多个可以注入的@Injectable,则选择最优先定义的@Injectable对象。
    当然,我们的测试程序要尽量避免这种情况出现。因为给哪个测试属性/测试参数加@Injectable,是人为控制的。

  2. 什么测试场景,我们要使用@Tested & @Injectable

显然,当我们需要手工管理被测试类的依赖时,就需要用到@Tested & @Injectable。
     两者搭配起来用,JMockit就能帮我们轻松搞定被测试类及其依赖注入细节。

原文地址:https://www.cnblogs.com/funkboy/p/12012522.html

时间: 2024-11-01 11:39:30

jMockit中文网备份 @Test&@Injectable的相关文章

jmockit中文网备份 @Mocked入门

当@Mocked修饰一个类时 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19  //@Mocked注解用途 public class MockedClassTest {     // 加上了JMockit的API @Mocked, JMockit会帮我们实例化这个对象,不用担心它为null     @Mocked     Locale locale;     // 当@Mocked作用于class     @Test     public void

jmockit中文网 dubbo bean

Dubbo是我们常用的RPC框架,在写单元测试需要调用Dubbo消费Bean时,如何模拟Dubbo消费Bean的行为呢? 就拿发邮件来说,通常,在代码中,我们是调用邮件的Dubbo服务来完成发送邮件的目的,于是我们会在Spring配置好的发邮件的Dubbo消费Bean,dubbo-consumer.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?xml version="1.0" encoding="utf-8"?>

jmockit中文网 expectations 入门

通过上面的例子,我们已经了解了Expectations的作用主要是用于录制.即录制类/对象的调用,返回值是什么. 录制脚本规范 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 new Expectations() {     // 这是一个Expectations匿名内部类     {           // 这是这个内部类的初始化代码块,我们在这里写录制脚本,脚本的格式要遵循下面的约定         //方法调用(可是类的静态方法调用,也可以

jmockit中文网 aop设置

在学习MockUp(API:MockUp)时, MockUp可以自定义方法体,覆盖类原有的方法. JMockit给我们提供了一个特别的方法,用于拦截所有方法,可以让我们在基于被Mock的方法做AOP. 比如我们想测试每个方法的时间性能. 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 //通过在mock时做AOP测试方法的时间性能 public c

jmockit 中文网 springbean

如今,我们的很多应用程序是基于Spring的,通过Spring IOC容器来管理我们的Java对象.所以这里单独提出对Spring Bean如何Mock方法. 以上述提到如何Mock类中的提到的AnOrdinaryClass为例,先把这个类配置在Spring的配置文件中 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?xml version="1.0" encoding="utf-8"?> <!--su

jmockit 中文网 构造函数中文代码块

有时候,有些编写不良好的类的构造函数,初始代码块,静态代码块存在大量的初始化逻辑,初始化会报错. 比如,有些类初始化的时候就去连结DB,连不上就报错.这很影响我们的测试程序的运行. 此时,我们需要把这些初始化逻辑Mock掉.用我们的Mock逻辑替代.要Mock这些初始化代码,很简单.见如下的例子: 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 //一个包含初始代码块的普通类  publi

jmockit中文网 定制结果

在学习Expectations(API:Expectations)时   ,在new Expectations{{}}代码中,返回的结果都比较简单.就是一个单一的对象.可是有时,这个返回的结果,可能是需要经历一些业务逻辑计算后,才知道返回什么的,此时,我们就需要定制返回结果了. 还是上例子吧. 还是以上文打招呼的例子来说. 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

jmockit 中文网 mq消息生产者

RocketMQ是我们常用的消息中间件,在运行单元测试时,我们可能不需要真正发送消息(除非是为了测试发送消息),也不想因为连结不上RocketMQ的Broker,NameServer而影响单元测试运行.   那我们该如何Mock RocketMQ消息生产者呢?  请看例子: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 //RocketMQ消息生产者 Mock  public class RocetMQProduce

常用书签

<!DOCTYPE NETSCAPE-Bookmark-file-1><!-- This is an automatically generated file. It will be read and overwritten. DO NOT EDIT! --><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"><TITLE>Bookmar