Mockito升级

这篇具有很好参考价值的文章主要介绍了Mockito升级。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

背景

系统是SpringBoot的,原来单元测试用的 Mockito,不过由于版本较低,对静态方法无法Mock,所以又引入了 PowerMock;

好长时间没动过了,现在刚好有一个项目需要写测试代码,顺便也把Mockito升升级;

现在Mockito版本已经到了 5.2.0了,不过需要Java11的支持;目前项目还使用的是Java8,因此只能使用到 Mockito4,最高版本为 4.11.0;

而且从Mockito3的某个版本开始,已经支持了 静态方法的Mock,所以可以暂时抛弃PowerMock了;

依赖:

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <version>${spring-boot.version}</version>
                <scope>test</scope>
            </dependency>

            <dependency>
                <groupId>org.mockito</groupId>
                <artifactId>mockito-core</artifactId>
                <version>${mockito-version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.mockito</groupId>
                <artifactId>mockito-inline</artifactId>
                <version>${mockito-version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.mockito</groupId>
                <artifactId>mockito-junit-jupiter</artifactId>
                <version>${mockito-version}</version>
                <scope>test</scope>
            </dependency>


        <mockito-version>4.11.0</mockito-version>

其实没必要依赖这么多artifact,也没细究,看例子这样service和http都可以进行Mock测试;

Mock整个类

ClassA,调用到 ClassB , 现在自己Mock生成一个ClassB;

@Component
public class ClassA {

    @Autowired
    ClassB classB;

    public void printA(int value ) {
        int a;
        a = value + classB.getValue();
        System.out.println("------------------------------------------------------");
        System.out.println("ClassA : a value is " + a);
        System.out.println("------------------------------------------------------");
    }

}
@Component
public class ClassB {

    public int getValue() {
        return 10;
    }

}

测试代码:

@RunWith(SpringRunner.class)
@SpringBootTest
public class SimpleTest {

    @Autowired
    ClassA classA;

    @MockBean
    ClassB classB;

    @Test
    public void Simple() {

        when(classB.getValue()).thenReturn(5);

        classA.printA(5);
    }
}

如果没有Mock掉ClassB,

classA.printA(5) 的结果应该是: 5 + 10 ,结果是 15;

mockito版本,单元测试

 Mock了ClassB,classB.getValue返回从10变成了5,结果应该显示10了

mockito版本,单元测试

Mock一些方法

有时候需要使用到原始的类,但是只对其中某些方法进行Mock:

@Component
public class ClassA {

    @Autowired
    ClassB classB;

    public int printA(int value ) {
        int a;
        a = value + classB.getValue();
        return a;
    }

    public int printB(int value ) {
        int b;
        b = value + classB.getValue();
        return b;
    }


}

正常情况下

@RunWith(SpringRunner.class)
@SpringBootTest
public class SimpleTest2 {

    @Autowired
    ClassA classA;

    @Test
    public void Simple() {

        System.out.println("printA : " + classA.printA(5) );

        System.out.println("printB : " + classA.printB(5) );
    }

}

printA(5) 和 printB(5) 结果应该是一样的:

mockito版本,单元测试

 

如果想Mock掉ClassA.printA, 让printA返回指定的值,那就需要对printA做处理:

在对printA函数做处理之前,首先要对 classA类进行包装:

方法1 :

    @Autowired
    ClassA classA;

改变成:

    @SpyBean
    ClassA classA;

 或者:


    @Autowired
    ClassA classA;

    @Test
    public void Simple() {

        classA = Mockito.spy(classA);

        。。。。。。
    }

然后对printA进行处理:

    @Test
    public void Simple() {

        classA = Mockito.spy(classA);

        when(classA.printA(anyInt())).thenReturn(100);

        System.out.println("printA : " + classA.printA(5) );

        System.out.println("printB : " + classA.printB(5) );
    }

结果:

mockito版本,单元测试

其中: 

when(classA.printA(anyInt())).thenReturn(100);

也可以写成

doReturn(100).when(classA).printA(anyInt());

静态方法的Mock

现在的Mockito也可以对静态方法做Mock

Bean类:

@Component
public class ClassB {

    public int getValue() {
        return 10;
    }

    public static int getStaticInt() {
        return 1;
    }
}

这里ClassB,多了一个静态方法: getStaticInt 

在ClassA中,使用这个静态方法:

@Component
public class ClassA {

    public int invokeClassBStatic(int value ) {
        return value + ClassB.getStaticInt();
    }

}

正常情况下,

@SpringBootTest
@RunWith(SpringRunner.class)
public class SimpleTest3 {

    @Autowired
    ClassA classA;

    @Test
    public void Simple() {

        classA.invokeClassBStatic(5);

    }
}

的结果是:

mockito版本,单元测试

现在Mock掉ClassB. getStaticInt,让它返回100,代码变成:

@SpringBootTest
@RunWith(SpringRunner.class)
public class SimpleTest3 {

    @Autowired
    ClassA classA;

    @Test
    public void Simple() {

        MockedStatic<ClassB> classBMockedStatic = Mockito.mockStatic(ClassB.class);
        classBMockedStatic.when(
                () -> ClassB.getStaticInt()
        ).thenReturn(100);

        System.out.println(classA.invokeClassBStatic(5));

    }
}

执行结果:

mockito版本,单元测试

 

对void函数进行Mock

用 doNoting().when()

用新的函数Mock掉老函数

对printA进行Mock

@RunWith(SpringRunner.class)
@SpringBootTest
public class SimpleTest4 {

    @SpyBean
    ClassA classA;

    @Test
    public void Simple() {

        classA = Mockito.spy(classA);

        when(classA.printA(anyInt())).thenAnswer((invocation) -> {
            int p =  invocation.getArgument(0);
            return p * 2;
        });

        System.out.println("printA : " + classA.printA(5));

        System.out.println("printB : " + classA.printB(5));
    }

}

结果:

mockito版本,单元测试

 

被Mock的对象执行原方法:

对于mock的对象,它的所有方法都会被打桩,不执行真实方法,除非使用doCallRealMethod。文章来源地址https://www.toymoban.com/news/detail-701064.html

Foo mock = mock(Foo.class);
doCallRealMethod().when(mock).someVoidMethod();

// 会执行实现方法 Foo.someVoidMethod()
mock.someVoidMethod();

调用原始方法,替换原始方法

ArgumentCaptor<Object> arg1 = ArgumentCaptor.forClass(Object.class);
ArgumentCaptor<Long> arg2 = ArgumentCaptor.forClass(Long.class);

// doNothing忽略方法调用,并把方法的2个参数进行捕获
Mockito.doNothing().when(businessService).noReturnMethod1(arg1.capture(), arg2.capture());

// 方法调用
String realArg1 = "我是参数1";
long realArg2 = 123567;
businessService.noReturnMethod1(realArg1, realArg2);

// 对捕获的参数进行断言
Assert.isTrue(realArg1.equals(arg1.getValue()), "");
Assert.isTrue(realArg2 == arg2.getValue(), "");

// void方法测试2,替换void方法
Mockito.doAnswer(invocation -> {
    Object objArg = invocation.getArgument(1);
    Long longArg = invocation.getArgument(0);
    System.out.println(objArg + "===" + longArg);

    // 对捕获的参数进行断言
    Assert.isTrue(realArg1.equals(objArg), "");
    Assert.isTrue(realArg2 == longArg, "");

    return invocation.callRealMethod();// 需要时,这里可以回调原始方法
}).when(businessService).noReturnMethod2(ArgumentMatchers.anyLong(), ArgumentMatchers.any());

businessService.noReturnMethod2(realArg2, realArg1);

到了这里,关于Mockito升级的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring单元测试+Mockito

    一,背景 单元测试基本上是开发逃不过的一个工作内容,虽然往往因为过于无聊,或者过于麻烦,而停止于项目的迭代之中,不了了之了。其实不是开发们懒,而是上头要求的测试覆盖率高,但是又没有好用的工具,导致工作积压,最后只能舍弃掉这部分。 最近发现Spring+

    2024年04月17日
    浏览(43)
  • 【单元测试】Mockito使用详解

    一个单元测试应该有如下特点: 应该是自动化的 应该可以快速运行 每个单元测试不应该依赖其它测试的结果和执行顺序,单元测试框架可以按任意的顺序执行每个测试 每个单元测试不应该依赖数据库,外部文件,或者任何长时间运行的任务。单元测试应该是独立的,不应该

    2024年04月15日
    浏览(87)
  • 单元测试与Mockito

    系列文章目录和关于我 最近在新公司第一次上手写代码,写了一个不是很难的业务逻辑代码,但是在我写单元测试的时候,发现自己对单元测试的理解的就是一坨,整个过程写得慢,还写得臭。造成这种局面我认为是因为: 对Mockito api是不是很熟悉 没有自己单元测试方法论

    2023年04月22日
    浏览(41)
  • Mockito单元测试基本使用

    本文参考: 【码农教程】手把手教你Mockito的使用 - 掘金 (juejin.cn) java - doReturn().when()与when().thenReturn() - 成长之路 - SegmentFault 思否 单元测试实践篇:Mock_阿里巴巴淘系技术团队官网博客的博客-CSDN博客 阿里是如何进行单元测试培训的?_Hollis Chuang的博客-CSDN博客 【Mockito】Mock

    2024年02月10日
    浏览(50)
  • Java单元测试之Mockito

    Mockito是一种Java Mock框架,主要就是用来做Mock测试的,它可以模拟任何Spring管理的Bean、模拟方法的返回值、模拟抛出异常等等,同时也会记录调用这些模拟方法的参数、调用顺序,从而可以校验出这个Mock对象是否有被正确的顺序调用,以及按照期望的参数被调用。 Mockito的特

    2024年02月13日
    浏览(50)
  • 【SpringBoot】mockito+junit 单元测试

    CommonServiceImpl 在方法 getSourceCodeMap() 调用了 ServiceA 的方法 list(QueryBO queryBo) 。 org.mockito.exceptions.base.MockitoException: No tests found in ClientSyncServiceImplTest Is the method annotated with @Test? Is the method public? 解决方案: Test引入 org.junit.Test 不要引入 org.junit.jupiter.api.Test 例如获取当前用户 moc

    2024年02月09日
    浏览(44)
  • 单元测试之- mock工具mockito

     常用的mock工具mockito 在编写单元测试时,需要mock依赖的对象,减少依赖对象对测试的影响,Mocktio是常用的mock工具之一,那么mockito提供了哪些功能呢? Mock对象的创建和配置:Mockito可以通过简单的语法创建mock对象,并允许你配置mock对象的行为。 Mock对象的验证:Mockito提供

    2024年02月13日
    浏览(41)
  • Junit5+Mockito单元测试详解

    1.宏观层面:AIR原则 A:Automatic(自动化) 全自动执行,输出结果无需人工检查,而是通过断言验证。 I:Independent(独立性) 分层测试,各层之间不相互依赖。 R:Repeatable(可重复) 可重复执行,不受外部环境( 网络、服务、中间件等)影响。 2.微观层面:BCDE原则 B: Bord

    2024年01月17日
    浏览(48)
  • Java单元测试浅析(JUnit+Mockito)

    Java测试我们应该都遇到过,一般我们会被要求做单元测试,来验证我们代码的功能以及效率。 这里来和大家一起探讨下有关单于测试。 是指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如C语言中单

    2024年02月06日
    浏览(62)
  • JUnit 5单元测试(三)—— Mockito 模拟

    上一篇讲了 JUnit 5单元测试(二)—— 断言,书接上文开始 JUnit 5单元测试(三)—— Mockito 模拟 想象下面这几种情况你该怎么单元测试: 1.A方法去数据库查询了数据进行了一些处理,该怎么单元测试; 2.在微服务项目中,A方法中调用了远程微服务B方法(或者B方法还没写好

    2024年02月15日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包