单元测试——Mock

2024-05-08 02:32
文章标签 单元测试 mock

本文主要是介绍单元测试——Mock,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

【背景】

        单元测试的目标是一次只验证一个方法,但是倘若遇到这样的情况:某个方法依赖于其他一些难以操控的东西,诸如网络、数据库,甚至是微软最新的股票价格,那我们该怎么办?

        要是你的测试依赖于系统的其他部分,甚至是系统的多个其他部分呢?在这种情况下,倘若不小心,你最终可能会发现自己几乎初始化了系统的每个组件,而这只是为了给一个测试创造足够的运行环境让它们可以运行起来。忙乎了大半天,看上去我们好像有点违背了测试的初衷了。这样不仅仅消耗时间,还给测试过程引入了大量的耦合因素,比如说,可能有人兴致冲冲地改变了一个接口或者数据库的一张表,突然,你那卑微的单元测试的神秘的挂掉了。在这种情况发生几次之后,即使是最有耐心的开发者也会泄气,甚至最终放弃所有的测试,那样的话后果就不能想像了。


【简介】

         mock就是在测试过程中,对于某些不容易构造或者 不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法。

        在实际的面向对象软件设计中,我们经常会碰到这样的情况,我们在对现实对象进行构建之后,对象之间是通过一系列的接口来实现。这在面向对象设计里是最自然不过的事情了,但是随着软件测试需求的发展,这会产生一些小问题。举个例子,用户A现在拿到一个用户B提供的接口,他根据这个接口实现了自己的需求,但是用户A编译自己的代码后,想简单模拟测试一下,怎么办呢?这点也是很现实的一个问题。我们是否可以针对这个接口来简单实现一个代理类,来测试模拟,期望代码生成自己的结果呢?

         幸运的是,有一种测试模式可以帮助我们:mock对象。Mock对象也就是真实对象在调试期的替代品。

何时使用Mock对象

1)    真实对象具有不可确定的行为(产生不可预测的结果,如股票的行情)

2)    真实对象很难被创建(比如具体的web容器)

3)    真实对象的某些行为很难触发(比如网络错误)

4)    真实情况令程序的运行速度很慢

5)    真实对象有用户界面

6)    测试需要询问真实对象它是如何被调用的(比如测试可能需要验证某个回调函数是否被调用了)

7)    真实对象实际上并不存在(当需要和其他开发小组,或者新的硬件系统打交道的时候,这是一个普遍的问题)

如何使用Mock对象

1、使用一个接口来描述这个对象
2、为产品代码实现这个接口

3、以测试为目的,在mock对象中实现这个接口


【实例】

下边我们以一个Demo:其中有一个Reminder()的方法,如果在下午5点之后调用该方法,就会播放对应的音频,我们需要测试其中的Reminder()方法。

这是整个Demo的总体架构:



1、创建产品代码类

首先,创建一个接口:Environmental

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;namespace Clock
{//接口public interface Environmental{//接口中的定义的方法:Now,返回类型为DataTimeDateTime Now { get; }//播放音频void PlayWavFile(string fileName);}
}

在产品SystemEnvironment类中,继承接口,实现接口中的方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;namespace Clock
{//SystemEnvironment类继承接口public class SystemEnvironment:Environmental {// //定义一个私有的变量:when,返回类型为DateTimeprivate DateTime when;//定义了一个构造函数SystemEnvironment,并传入了一个when对象,when的类型为DateTime类型public SystemEnvironment(DateTime when){this.when = when;        }//具体实现接口中的方法public DateTime Now {get {return DateTime.Now;}       }//重写playWavFile方法public void PlayWavFile(string fileName){throw new NotImplementedException();}}
}

定义一个Checker类,来调用接口方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;namespace Clock
{//定义一个Checker类,来调用接口中的方法public class Checker{Environmental env;public Checker(Environmental env) {this.env = env;}public void Reminder() {DateTime Now = env.Now;if (Now.Hour >= 17){env.PlayWavFile("***.wav");}}}
}

下边是一个控制台类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;namespace Clock
{public class Program{//控制台应用程序static void Main(string[] args){ }//定义一个QuittingTime方法public void QuittingTime() {DateTime when = new DateTime(2015, 3, 6, 15, 00, 0);SystemEnvironment se = new SystemEnvironment(when);Checker checker = new Checker(se);checker.Reminder();}}
}

2、然后编写测试类TestClock(需要添加对nunit.framework的引用)

首先,通过创建Mock测试类MockSystemEnvironment类,来继承接口Environmental 。MockSystemEnvironment类就是用来代替产品代码中的SystemEnvironment类。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Clock;namespace TestClock
{public class MockSystemEnvironment:Environmental {//定义一个私有的变量:currentTime,返回类型为DateTimeprivate DateTime currentTime;//定义了一个构造函数MockSystemEnvironment,并传入了一个when对象,when的类型为DateTime类型public MockSystemEnvironment(DateTime when) {//将对象when的值赋给上边定义的私有变量currentTimecurrentTime = when;}//实现方法Nowpublic DateTime Now {get {return currentTime;}}//定义一个IncrementMinutes方法,作用是:给currentTime这个时间,加上指定的分钟数,就可以控制Mock对象所返回的日期和时间public void IncrementMinutes(int minutes) {currentTime = currentTime.AddMinutes(minutes);}private bool soundWasPlayed = false;public void PlayWavFile(string fileName) {soundWasPlayed = true;}public bool CheckAndResetSound() {bool value = soundWasPlayed;soundWasPlayed = false;return value;}}
}

然后,编写具体的测试代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Clock;namespace TestClock
{[TestFixture ]public  class TestChecker{[Test]public void QuittingTime() {//创建了一个DateTime对象:When,并给其赋值为2015, 3, 6, 15, 00, 0DateTime when = new DateTime(2015, 3, 6, 15, 00, 0);MockSystemEnvironment env = new MockSystemEnvironment(when);     Checker checker = new Checker(env);//在16:45时,闹钟不响checker.Reminder();Assert.IsFalse(env.CheckAndResetSound(), "16:45");//现在,在16:45的基础上加上15分钟env.IncrementMinutes(15);checker.Reminder();Assert.IsTrue(env .CheckAndResetSound (),"17:00");}}
}

PS:在具体的测试中,需要根据实际设定时间。

【结语】

    
    上边我们通过一个简单的Demo来介绍了一下Mock,Demo很简单,但是Mock的复杂之处在于如何在实际项目中去使用。文章中只是介绍了Mock的冰山一角,更多的东西还需要我们去研究、探索。
    
    在项目中如何使用Mock,还需要我们多实践,多动手去做,实践出真知!
        


这篇关于单元测试——Mock的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/969054

相关文章

企业级Web项目中应该如何做单元测试、集成测试和功能测试?

先自我介绍下: 本人有过10年测试经验,也参与过公安部网络安全产品测试交付、华为4G 网络设备测试交付、腾讯QQ空间APP产品测试交付。 关于“企业级Web项目中应该如何做单元测试、集成测试和功能测试”这个问题,我想给大家唠唠,我所知道的这方面知识。 一、首先简单说说这三种测试有什么区别 【单元测试】、【集成测试】和【功能测试】三种测试的是什么,三者有什么区别和联系,如果想更清晰的了解

tessy 单元测试 TDE 界面 数据无法填充:the test object interface is incomplete

目录 1,失败现象 2,失败原因 3,解决办法 1,失败现象         函数名字前的图标高度缩小为正常的一半,TDE界面的数据无法填充。错误提示为题目中的英文。 2,失败原因         TIE界面,此函数的参数的 passing 方向有 unknown,未正确识别。 3,解决办法         将 interface 栏的所有参数的 passing 和

【Rust日报】 2019-05-25:Mockiato - 一個嚴格友好的Mock測試庫

Into The Wild 有人用rust寫了一個很像lf2(Little Fighter 2)的2.5D動作遊戲 Read more Rust官网的国际化支持,在找人翻译 Read more Read more 「讨论」对于单人主力维护的项目如何看待 楼主覺得 actix 和 rust-postgres 很棒 但發現這兩個庫都只有一個大佬在當主力開發,他覺得庫只有一人維護對大公司來

SpringBoot单元测试报错:java.lang.NoSuchMethodError: org.junit.platform.commons.util.ReflectionUtils

当我在SpringBoot项目中想做单元测试时,运行就报以下错误     我的配置信息都是正确的,瞬间懵逼了,网上都说是Junit5与IDEA版本不兼容,需要升级IDEA的版本,或者使用Junit4来进行单元测试。IDEA升级怕又要破解,很是蛋疼,所以还是想想使用Junit4来做测试了。     网上也找了半天也没有太全的说明,自己研究了下,竟然搞成了,前戏完成,上菜了

Python单元测试框架-unittest

参考 https://docs.python.org/2/library/unittest.html#organizing-tests import unittestclass TestStringMethods(unittest.TestCase):def test_upper(self):self.assertEqual('foo'.upper(), 'FOO')def test_isup

Spring boot 单元测试类

在Spring Boot中,我们可以使用Spring Boot Test框架来进行单元测试。这是一个非常强大的工具,可以帮助我们模拟Spring环境,进行各种测试,如集成测试、容器测试等。 以下是一些Spring Boot 单元测试的示例。 基本的Spring Boot测试 @RunWith(SpringRunner.class)@SpringBootTestpublic class S

mock-前端数据模拟

简介 数据模拟不是开发流程中的必要一环 Json-server 简介: json-server 是一个简单的 Node.js 服务端应用程序,这个工具的主要作用是提供一个模拟的后端服务,可以在前端开发过程中独立于后端进行简单工作。 使用: 1、 安装 Npm install -g json-server 2、 创建json文件 这个json文件在哪创建都可以,我只是为了方便在我

vitest-前端单元测试

简介 Vitest 是一个轻量级、快速且功能强大的测试框架,它基于 Vite 提供了一种极速的测试体验。Vitest 尤其适合用于 Vite 项目,但同样可以与其他前端项目(如使用 webpack 构建的项目)集成使用。 安装 npm I vitest -D 为了执行测试,请将以下部分添加到你的 package.json 文件中: 通常会在src目录下常见一个tests目录来存放编写的

5分钟了解单元测试

🍅 视频学习:文末有免费的配套视频可观看 🍅 点击文末小卡片 ,免费获取软件测试全套资料,资料在手,涨薪更快 一、什么是单元测试? 单元测试是指,对软件中的最小可测试单元在与程序其他部分相隔离的情况下进行检查和验证的工作,这里的最小可测试单元通常是指函数或者类;单元测试属于最严格的软件测试手段,是最接近代码底层实现的验证手段,可以在软件开发的早期以最小的成本保证局部代码的质量。另外,

Jenkins构建Android项目持续集成之单元测试及代码覆盖率

http://blog.csdn.net/it_talk/article/details/50267573 http://blog.csdn.net/it_talk/article/details/50267573 http://blog.csdn.net/it_talk/article/details/50267573 http://blog.csdn.net/it_talk/art