Mockito-部分mock测试使用

什么是类的部分mock(partial mock)?
A:部分mock是说一个类的方法有些是实际调用,有些是使用mockito的stubbing(桩实现)。

为什么需要部分mock?

A:当需要测试一个组合方法(一个方法需要其它多个方法协作)的时候,某个叶子方法(只供别人调用,自己不依赖其它反复)已经被测试过,我们其实不需要再次测试这个叶子方法,so,让叶子打桩实现返回结果,上层方法实际调用并测试。

mockito实现部分mock的两种方式:spy和callRealMethod()

spy实现:

package spy;

import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import java.util.LinkedList;
import java.util.List;

import org.junit.Test;

public class SpyDemo {

    @Test
    public void spy_Simple_demo(){
        List<String> list = new LinkedList<String>();
        List<String> spy = spy(list);
        when(spy.size()).thenReturn(100);  

        spy.add("one");
        spy.add("two");  

/*        spy的原理是,如果不打桩默认都会执行真实的方法,如果打桩则返回桩实现。
        可以看出spy.size()通过桩实现返回了值100,而spy.get(0)则返回了实际值*/
        assertEquals(spy.get(0), "one");
        assertEquals(100, spy.size());
    }

    @Test
    public void spy_Procession_Demo() {
        Jack spyJack = spy(new Jack());
        //使用spy的桩实现实际还是会调用stub的方法,只是返回了stub的值
        when(spyJack.go()).thenReturn(false);
        assertFalse(spyJack.go()); 

        //不会调用stub的方法
        doReturn(false).when(spyJack).go();
        assertFalse(spyJack.go());
    } 

}

class Jack {
    public boolean go() {
        System.out.println("I say go go go!!");
        return true;
    }
}

Spy类就可以满足我们的要求。如果一个方法定制了返回值或者异常,那么就会按照定制的方式被调用执行;如果一个方法没被定制,那么调用的就是真实类的方法。

如果我们定制了一个方法A后,再下一个测试方法中又想调用真实方法,那么只需在方法A被调用前,调用Mockito.reset(spyObject);就行了。

package spy;

import static org.mockito.Mockito.when;

import org.mockito.Mockito;

public class TestMockObject {

    public static void main(String[] args) {

        TestMockObject mock = Mockito.mock(TestMockObject.class);
        System.out.println(mock.test1());
        System.out.println(mock.test2());

        TestMockObject spy = Mockito.spy(new TestMockObject());
        System.out.println(spy.test1());
        System.out.println(spy.test2());

        when(spy.test1()).thenReturn(100);
        System.out.println(spy.test1());

        Mockito.reset(spy);
        System.out.println(spy.test1());
        System.out.println(spy.test2());

        when(spy.test1()).thenReturn(104);
        System.out.println(spy.test1());
    }

    public int test1() {
        System.out.print("RealTest1()!!! - ");
        return 1;
    }

    public int test2() {
        System.out.print("RealTest2()!!! - ");
        return 2;
    }

}

输出为:

0
0
RealTest1()!!! - 1
RealTest2()!!! - 2
RealTest1()!!! - 100
RealTest1()!!! - 1
RealTest2()!!! - 2
RealTest1()!!! - 104

要注意的是,对Spy对象的方法定制有时需要用另一种方法:
===============================================================================
Importantgotcha on spying real objects!

Sometimes it‘s impossible to usewhen(Object) for stubbing spies. Example:
List list = new LinkedList();
List spy = spy(list);

//Impossible: real method is called so spy.get(0) throwsIndexOutOfBoundsException (the list is yet empty)
when(spy.get(0)).thenReturn("foo");

//You have to use doReturn() for stubbing
doReturn("foo").when(spy).get(0);
===============================================================================
因为用when(spy.f1())会导致f1()方法被真正执行,所以就需要另一种写法。

http://blog.csdn.net/dc_726/article/details/8568537

callRealMethod()实现

Use doCallRealMethod() when you want to call the real implementation of a method.

As usual you are going to read the partial mock warning: Object oriented programming is more less tackling complexity by dividing the complexity into separate, specific, SRPy objects. How does partial mock fit into this paradigm? Well, it just doesn‘t... Partial mock usually means that the complexity has been moved to a different method on the same object. In most cases, this is not the way you want to design your application.

However, there are rare cases when partial mocks come handy: dealing with code you cannot change easily (3rd party interfaces, interim refactoring of legacy code etc.) However, I wouldn‘t use partial mocks for new, test-driven & well-designed code.

See also javadoc Mockito.spy(Object) to find out more about partial mocks. Mockito.spy() is a recommended way of creating partial mocks. The reason is it guarantees real methods are called against correctly constructed object because you‘re responsible for constructing the object passed to spy() method.

Example:


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

   // this will call the real implementation of Foo.someVoidMethod()
   mock.someVoidMethod();
 

See examples in javadoc for Mockito class

Returns:
stubber - to select a method for stubbing

package callRealMethod;

import org.junit.Test;
import static org.mockito.Mockito.*;

public class CallMethodDemo {
    @Test
    public void callRealMethodTest() {
        Jerry jerry = mock(Jerry.class);  

        doCallRealMethod().when(jerry).goHome();
        doCallRealMethod().when(jerry).doSomeThingB();  

        jerry.goHome();  

        verify(jerry).doSomeThingA();
        verify(jerry).doSomeThingB();
    }
}

class Jerry {
    public void goHome() {
        doSomeThingA();
        doSomeThingB();
    }  

    // real invoke it.
    public void doSomeThingB() {
        System.out.println("good day");  

    }  

    // auto mock method by mockito
    public void doSomeThingA() {
        System.out.println("you should not see this message.");  

    }
}

通过代码可以看出Jerry是一个mock对象, goHome()和doSomeThingB()是使用了实际调用技术,而doSomeThingA()被mockito执行了默认的answer行为(这里是个void方法,so,什么也不干)。

总结:

    spy和callrealmethod都可以实现部分mock,唯一不同的是通过spy做的桩实现仍然会调用实际方法(我都怀疑这是不是作者的bug)。

   ★ 批注:spy方法需要使用doReturn方法才不会调用实际方法。

mock技术是实施TDD过程必备的装备,熟练掌握mockito(或者其他工具)可以更有效的进行测试。虽然mockito作者也觉得部分测试不是好的设计,但是在java这样一个不是完全面向对象技术的平台上,我们其实没必要过分纠结这些细节,简洁,可靠的代码才是我们需要的。

时间: 2024-12-21 20:44:29

Mockito-部分mock测试使用的相关文章

【翻译】Java使用Mockito进行Mock测试

我们所有人在编写单元测试的时候面临的巨大挑战是模块对其他组件的依赖.同时花费大量的时间和精力去配置依赖的组件环境是一件出力不讨好的事情.使用Mock是一种有效地方式替代其他组件用来继续我们的单元测试构建过程. 接下来我将会展示一个使用mock技术的实例.这里我有一个数据访问层(简称DAL),建立一个类,提供应用程序访问和修改数据库中数据的基本API.接着我会测试这个DAL实例,但并不真正连接数据库.使用DAL类的目的是帮助我们隔离应用程序代码和数据显示层. 让我们通过下面的命令行创建一个java

mock测试框架Mockito

无论是敏捷开发.持续交付,还是测试驱动开发(TDD)都把单元测试作为实现的基石.随着这些先进的编程开发模式日益深入人心,单元测试如今显得越来越重要了.在敏捷开发.持续交付中要求单元测试一定要快(不能访问实际的文件系统或数据库),而TDD经常会碰到协同模块尚未开发的情况,而mock技术正是解决这些问题的灵丹妙药. mock技术的目的和作用是模拟一些在应用中不容易构造或者比较复杂的对象,从而把测试与测试边界以外的对象隔离开. 我们可以自己编写自定义的Mock对象实现mock技术,但是编写自定义的Mo

Mock测试框架(Mockito为例)

在做单元测试的时候,有的时候用到的一些类,我们构造起来不是那么容易,比如HttpRequest,或者说某个Service依赖到了某个Dao,想构造service还得先构造dao,这些外部对象构造起来比较麻烦. 所以出现了Mock! 我们可以用 Mock 工具来模拟这些外部对象,来完成我们的单元测试. 实现Mock技术的优秀开源框架有很多,下面以Mockito为例,用几个简单例子来介绍Mock工具的基本使用: 1.Mockito的第一个示例 1 @Test 2 public void simple

使用PowerMock进行Mock测试

安装 下载地址:https://github.com/jayway/powermock/wiki/Downloads.下载" Mockito and JUnit including dependencies"版本.当前版本为”powermock-mockito-junit-1.6.3.zip". IntelliJ IDEA的设置如下: 右击工程,选择“Open Module Settings” 按下“ALT + Insert”,选择“Jars or directories..

简单介绍如何使用PowerMock和Mockito来mock 1. 构造函数 2. 静态函数 3. 枚举实现的单例 4. 选择参数值做为函数的返回值(转)

本文将简单介绍如何使用PowerMock和Mockito来mock1. 构造函数2. 静态函数3. 枚举实现的单例4. 选择参数值做为函数的返回值5. 在调用mock出来的方法中,改变方法参数的值 一点简要说明:Mockito其实已经可以满足大部分的需求,但是它的实现机制是使用cglib来动态创建接口的类的实例.但是这种实现方式不能用于构造函数和静态函数,因为那需要使用类的字节码(比如使用javassist). 所以我们才需要结合使用PowerMock. 1. mock构造函数, 如果有代码没有

java的mock测试框架

无论是敏捷开发.持续交付,还是测试驱动开发(TDD)都把单元测试作为实现的基石.随着这些先进的编程开发模式日益深入人心,单元测试如今显得越来越重要了.在敏捷开发.持续交付中要求单元测试一定要快(不能访问实际的文件系统或数据库),而TDD经常会碰到协同模块尚未开发的情况,而mock技术正是解决这些问题的灵丹妙药. mock技术的目的和作用是模拟一些在应用中不容易构造或者比较复杂的对象,从而把测试与测试边界以外的对象隔离开. 我们可以自己编写自定义的Mock对象实现mock技术,但是编写自定义的Mo

使用PowerMockito和Mockito进行模拟测试,包括静态方法测试,私有方法测试等

依赖:这个很重要,不同版本用法也有点区别: <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> <version>2.0.2-beta</version> <scope>test</scope> </dependency> <dependency> <group

小程聊微服务-基于dubbo的mock测试系统

一.说在前面 基于微服务或者SOA的自动化测试系统每个公司都有自己的特有的,我今天就主要介绍一下,我们研发的一套mock测试系统. 二.目前面临的问题 1.测试人员面临的测试问题 我公司目前用的是基于Dubbo的微服务改造,服务之间的调用链路冗长,每个服务又是单独的团队在维护,每个团队又在不断的演进和维护各个服务,那么对测试人员将是非常大的挑战. 测试人员每次进行功能测试的时候,测试用例每次都需要重新写一遍,无法将测试用例的数据沉淀,尤其是做自动化测试的时候,测试人员准备测试数据就需要很长时间,

mock测试到底是什么?

?    ?经常听人说mock测试,究竟什么是mock测试呢?mock测试能解决什么问题?mock测试要如何做呢?今天为大家做简单介绍,之后会有详细的mock测试,感谢大家对测试梦工厂的持续关注. 概念 ?    ?mock测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法. MockObject ?    ?使用Mock Object进行测试,主要是用来模拟那些在应用中不容易构造(如HttpServletRequest必须在Servlet容器

Spring自带mock测试Controller

转自:http://blog.csdn.net/yin_jw/article/details/24726941 分类: Spring开源框架2014-04-29 17:01 1786人阅读 评论(2) 收藏 举报 Spring自带mock测试Contro 准备SpringMVC环境 注意:使用mock测试需要引入spring-test包 Base类:加载配置文件 [java] view plaincopy package com.wyy.snail.user.controller; import