当前位置:网站首页 > 技术博客 > 正文

mock测试入门



 是当前最流行的 单元测试  框架。采用  框架,我们可以 虚拟 出一个 外部依赖,降低测试 组件 之间的 耦合度,只注重代码的 流程与结果,真正地实现测试目的。

 的中文译为仿制的,模拟的,虚假的。对于测试框架来说,即构造出一个模拟/虚假的对象,使我们的测试能顺利进行下去。

 测试就是在测试过程中,对于某些 不容易构造(如  必须在  容器中才能构造出来)或者不容易获取 比较复杂 的对象(如  中的 对象),用一个 虚拟 的对象( 对象)来创建,以便测试方法。

单元测试 是为了验证我们的代码运行正确性,我们注重的是代码的流程以及结果的正确与否。

对比真实运行代码,可能其中有一些 外部依赖 的构建步骤相对麻烦,如果我们还是按照真实代码的构建规则构造出外部依赖,会大大增加单元测试的工作,代码也会参杂太多非测试部分的内容,测试用例显得复杂难懂。

采用  框架,我们可以 虚拟 出一个 外部依赖,只注重代码的 流程与结果,真正地实现测试目的。

  1. 可以很简单的虚拟出一个复杂对象(比如虚拟出一个接口的实现类);
  2. 可以配置  对象的行为;
  3. 可以使测试用例只注重测试流程与结果;
  4. 减少外部类、系统和依赖给单元测试带来的耦合。

如图所示,使用  的大致流程如下:

  1. 创建 外部依赖 的  对象, 然后将此  对象注入到 测试类 中;
  2. 执行 测试代码
  3. 校验 测试代码 是否执行正确。

在  的  中添加如下内容:

 

这里稍微解释下:

  • : 用于 本地单元测试,其测试代码路径位于 
  • : 用于 设备测试,即需要运行  设备进行测试,其测试代码路径位于 
mockito-core最新版本可以在 Maven 中查询:mockito-core。 mockito-android最新版本可以在 Maven 中查询:mockito-android

普通单元测试使用 ,路径:

这里摘用官网的 :

 

这里  了一个 (这里只是为了用作  示例,通常对于  这种简单的类对象创建而言,直接  一个真实的对象即可,无需进行 ), 会检验对象是否在前面已经执行了相关行为,这里  在  之前已经执行了  和  行为,所以 会通过。

 

这里对几个比较重要的点进行解析:

when(mockedList.get(0)).thenReturn("first")

这句话  会解析为:当对象  调用 方法,并且参数为  时,返回结果为,这相当于定制了我们  对象的行为结果( 对象为 ,指定其行为 ,则返回结果为 )。

mockedList.get(999)

由于  没有指定  的行为,所以其结果为 。因为  的底层原理是使用  动态生成一个 代理类对象,因此, 出来的对象其实质就是一个 代理,该代理在 没有配置/指定行为 的情况下,默认返回 空值

上面的  使用的是 静态方法  模拟出一个实例,我们还可以通过注解  也模拟出一个实例:

 

对于标记有 , ,  等注解的成员变量的 初始化 到目前为止有  种方法:

  1. 对  测试类添加 
  2. 在标示有  方法内调用初始化方法:

上面的测试用例,对于  等注解的成员变量的初始化又多了一种方式 。规则  会自动帮我们调用  去 实例化 出 注解 的成员变量,我们就无需手动进行初始化了。

 
  • 对于所有方法, 对象默认返回 ,原始类型/原始类型包装类 默认值,或者 空集合。比如对于  类型,则返回 ,对于  则返回 。
  • 行为配置()是可以被复写的:比如通常的对象行为是具有一定的配置,但是测试方法可以复写这个行为。请谨记行为复写可能表明潜在的行为太多了。
  • 一旦配置了行为,方法总是会返回 配置值,无论该方法被调用了多少次。
  • 最后一次行为配置是更加重要的,当你为一个带有相同参数的相同方法配置了很多次,最后一次起作用。

 通过参数对象的  方法来验证参数是否一致,当需要更多的灵活性时,可以使用参数匹配器:

 

参数匹配器 允许更加灵活的 验证 和 行为配置。更多 内置匹配器 和 自定义参数匹配器 例子请参考:,

注意:如果使用了参数匹配器,那么所有的参数都需要提供一个参数匹配器。
 

类似 , 这类匹配器并不返回匹配数值。他们内部记录一个 匹配器堆栈 并返回一个空值(通常为 )。这个实现是为了匹配  编译器的 静态类型安全,这样做的后果就是你不能在 检验/配置方法 外使用 , 等方法。

 

校验次数方法常用的有如下几个:

|Method |Meaning| |:------|:-------| |times(n)| 次数为n,默认为1(times(1))| |never()| 次数为0,相当于times(0)| |atLeast(n)|最少n次| |atLeastOnce()| 最少一次| |atMost(n)| 最多n次 |

 

有时对于一些行为,有先后顺序之分,所以,当我们在校验时,就需要考虑这个行为的先后顺序:

 

对于同一个方法,如果我们想让其在 多次调用 中分别 返回不同 的数值,那么就可以使用存根连续调用:

 

也可以使用下面更简洁的存根连续调用方法:

 
注意:存根连续调用要求必须使用链式调用,如果使用的是同个方法的多个存根配置,那么只有最后一个起作用(覆盖前面的存根配置)。
 

对于 返回类型 为  的方法,存根要求使用另一种形式的  函数,因为编译器要求括号内不能存在  方法。

例如,存根一个返回类型为  的方法,要求调用时抛出一个异常:

 

前面使用的都是  出来一个对象。这样,当 没有配置/存根 其具体行为的话,结果就会返回 空类型。而如果使用 特务对象(),那么对于 没有存根 的行为,它会调用 原来对象 的方法。可以把  想象成局部 。

 
注意:由于 spy 是局部 mock,所以有时候使用 when(Object) 时,无法做到存根作用。此时,就可以考虑使用 doReturn() | Answer() | Throw() 这类方法进行存根:
 

 并不是 真实对象 的 代理。相反的,它对传递过来的 真实对象 进行 克隆。所以,对 真实对象 的任何操作, 对象并不会感知到。同理,对  对象的任何操作,也不会影响到 真实对象

当然,如果使用  进行对象的 局部 ,通过  方法也是可以的:

 

以 行为驱动开发 的格式使用 //given //when //then 注释为测试用法基石编写测试用例,这正是  官方编写测试用例方法,强烈建议使用这种方式测试编写。

 
 

构造器,方法,成员变量依赖注入 使用  注解时, 会检查 类构造器方法或 成员变量,依据它们的 类型 进行自动 。

 

成员变量  类型为 ,它的上面标识别了 。这意味着要  出 , 需要先自动  出  所需的 构造参数(即: 和 ),最终  得到一个 ,赋值给 。

 允许在  的时候获取 方法参数内容,这使得我们能在 测试过程 中能对 调用方法参数 进行 捕捉 并 测试

 
  1. 不能  静态方法;
  2. 不能  构造器;
  3. 不能  和  方法。

最后感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走

 这些资料,对于从事【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!凡事要趁早,特别是技术行业,一定要提升技术功底。希望对大家有所帮助…….有需要的小伙伴可以点击下方小卡片免费领取

版权声明


相关文章:

  • l298npwm调速程序2025-05-21 15:30:00
  • button.css2025-05-21 15:30:00
  • struct timeval结构体2025-05-21 15:30:00
  • c assert函数2025-05-21 15:30:00
  • 内链接sql2025-05-21 15:30:00
  • 积分运算电路公式推导2025-05-21 15:30:00
  • 火车头采集器采集规则2025-05-21 15:30:00
  • 服务器硬件知识普及篇(需要配置服务器的朋友可以参考)2025-05-21 15:30:00
  • crc8和crc32区别2025-05-21 15:30:00
  • jm怎么用三步骤2025-05-21 15:30:00