职场人们天天说的接口Mock测试,今天我终于搞懂了

Posted 软件测试君

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了职场人们天天说的接口Mock测试,今天我终于搞懂了相关的知识,希望对你有一定的参考价值。

01 关于Mock测试

01 含义和目的

1、什么是Mock测试?

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

2、为什么要进行Mock测试?

Mock是为了解决不同的单元之间由于耦合而难于开发、测试的问题。所以,Mock既能出现在单元测试中,也会出现在集成测试、系统测试过程中。Mock 最大的功能是帮你把单元测试的耦合分解开,如果你的代码对另一个类或者接口有依赖,它能够帮你模拟这些依赖,并帮你验证所调用的依赖的行为。

比如一段代码有这样的依赖:

当我们需要测试A类的时候,如果没有 Mock,则我们需要把整个依赖树都构建出来,而使用 Mock 的话就可以将结构分解开,像下面这样:

02 Mock对象适用场景

需要将当前被测单元和其依赖模块独立开来,构造一个独立的测试环境,不关注被测单元的依赖对象,只关注被测单元的功能逻辑。

比如被测代码中需要依赖第三方接口返回值进行逻辑处理,可能因为网络或者其他环境因素,调用第三方经常会中断或者失败,无法对被测单元进行测试,这个时候就可以使用mock技术来将被测单元和依赖模块独立开来,使得测试可以进行下去。

被测单元依赖的模块尚未开发完成,而被测单元需要依赖模块的返回值进行后续处理。

① 前后端项目中,后端接口开发完成之前,接口联调;

② 依赖的上游项目的接口尚未开发完成,需要接口联调测试;

比如service层的代码中,包含对Dao层的调用,但是,DAO层代码尚未实现

被测单元依赖的对象较难模拟或者构造比较复杂。

比如支付宝支付的异常条件有很多,但是模拟这种异常条件很复杂或者无法模拟,比如,查询聚划算的订单结果,无法在测试环境进行模拟。

03 Mock测试的优势

1、团队可以并行工作

有了Mock,前后端人员只需要定义好接口文档就可以开始并行工作,互不影响,只在最后的联调阶段往来密切;后端与后端之间如果有接口耦合,也同样能被Mock解决;测试过程中如果遇到依赖接口没有准备好,同样可以借助Mock;不会出现一个团队等待另一个团队的情况。这样的话,开发自测阶段就可以及早开展,从而发现缺陷的时机也提前了,有利于整个产品质量以及进度的保证

2、开启TDD模式,即测试驱动开发

单元测试是TDD实现的基石,而TDD经常会碰到协同模块尚未开发完成的情况,但是有了mock,这些一切都不是问题。当接口定义好后,测试人员就可以创建一个Mock,把接口添加到自动化测试环境,提前创建测试。

3、可以模拟那些无法访问的资源

比如说,你需要调用一个“墙”外的资源来方便自己调试,就可以自己Mock一个。

4、隔离系统

假如我们需要调用一个post请求,为了获得某个响应,来看当前系统是否能正确处理返回的“响应”,但是这个post请求会造成数据库中数据的污染,那么就可以充分利用Mock,构造一个虚拟的post请求,我们给他指定返回就好了。

5、可以用来演示

假如我们需要创建一个演示程序,并且做了简单的UI,那么在完全没有开发后端服务的情况下,也可以进行演示。说到演示了,假如你已经做好了一个系统,并且需要给客户进行演示,但是里面有些真实数据并不想让用户看到,那么同样,你可以用Mock接口把这些敏感信息接口全部替换。

6、测试覆盖度

假如有一个接口,有100个不同类型的返回,我们需要测试它在不同返回下,系统是否能够正常响应,但是有些返回在正常情况下基本不会发生,比如,我们需要测试在当接口发生500错误的时候,app是否崩溃,别告诉我你一定要给服务端代码做些手脚让他返回500 。而使用mock,这一切就都好办了,想要什么返回就模拟什么返回,不用再担心我的测试覆盖度了!

04 Mock测试存在的问题

使用Mock测试有时可以提高团队的开发效率,但当B、C都开发完成代码后,这时应该把E2E测试代码从使用Mock测试改为调用真实的模块,以避免出现模块之间集成部分漏测的问题。这里说mock存在的问题,主要是让开发和测试不要过分的依赖/相信mock接口。

使用mock时,切记的几点:

  • 测试人员不应该被覆盖率高的E2E自动化测试所迷惑,覆盖率高不代表没有问题。尤其在接手新项目中,需要查看E2E测试中有没有使用Mock测试,进一步去判断这些地方使用Mock测试是否合理,这些Mock测试是否应该换成真实模块间的调用和集成。

  • 当把mock接口换成实际接口后,测试/开发也必须把之前的测试重新做一遍。

ps:当你使用mock接口来提高效率,请注意:

你的工作量其实是比 直接只用实际接口 多了 一倍的。如果测试时偷懒,替换成实际接口后,只是简单测试,那么 当实际接口和mock预期接口有差异时,故障便和你相遇了。

建议: mock接口只能主流程联调/ 异常返回测试,不要过分依赖mock接口进行测试。

  • 测试完毕,上线前请一定确保 为了mock而做的相关代码/配置文件的修改,已经完全恢复了。

建议:上线checklist中条条列出,并上线前review

02 Mock测试方式

01 Mock Server-Moco

这是一个jar包,只要执行该jar包,指定配置文件,就可开启一个http服务器提供服务,并且修改配置文件后也无需重启服务,支持动态加载。我使用的是moco-runner-0.10.2-standalone.jar,运行方式如下:

```java -jar moco-runner-0.10.2-standalone.jar start -p 8080 -c XXX.json```
XXX.json就是我们的mock配置文件,比如:
[    
          
      "description": "api 1",        
      "request" :
                      
             "method" : "get",        
             "uri" : "/foo"        
           ,        

      "response": 
            
      "json": "foo":"bar"        
          
   
]

以上就可以实现当我们访问127.0.0.0:8080/foo时,返回一个json为“foo”:“bar”。

02 fiddler

fiddler大家都很熟了,在windows环境可以随便自定义返回内容,但一个很大的缺点是,它不跨平台,而我们平时的很多场景下是需要在Linux下进行mock的。

还有一些其他mock工具,大多都是通过编写js代码或者python、java等代码来达到mock目的,此处就不再介绍了。

在选择mock工具时,可参考以下几个方面:

  • 一是数据要好管理,别让我管理一堆文件;

  • 二是mock接口最好可以设置成和真实接口完全一致,这样就只需要切换hosts就可以切换mock接口和真实接口,不需要修改代码;

  • 三是跨平台,mock接口在windows和Linux下都需要可用。至于跨域、动态加载什么的,这是必须条件。

03 Mock测试示例

使用Fiddler进行Mock测试,这种调试方式适用于rest接口调试,web界面调试等。

测试工程师在做测试时,也需要服务器返回一些特殊的数据来做测试,使用 Fiddler AutoResponder功能来伪造测试数据(创建虚拟对象),能大大减少测试工程师的工作量。

1、Fiddler AutoResponder工作原理

使用Fiddler可以替换自动返回的一个【伪造】的HTTP响应,这与使用断点修改HTTP响应类似,只不过AutoResponder是自动的,操作更加方便。即浏览器发出的HTTP请求并没有到达服务器,而是被Fiddler直接返回了一个【伪造】的HTTP响应。

2、使用Fiddler进行Mock测试

  • 接口抓包-----找到要mock的接口

以掘金首页为例,找到下面的接口 https://gold-tag-ms.juejin.im/v1/categories

  • 复制接口数据到本地

在接口上进行右键点击,选择save -> …and Open as Local File -> 默认会保存至桌面,示例中的数据,保存到了桌面的test.json

  • 修改数据

修改保存到本地的json文件,示例中仅修改了页面的标签数据。

  • 替换json文件

在web session 面板中找到对应的请求,然后将其拖到AutoResponder面板中,在RuleEditor中单击“Find a file…”,选择本地json文件的路径。

  • 激活规则

选中“Enable rules”,激活规则。选中“Unmatched requests passthrough",放行不匹配的HTTP请求。

  • save,刷新页面

单击“Save”按钮。只需修改本地保存的json文件,然后刷新浏览器(或直接访问接口),就可以看到效果了。

下面是配套资料,对于做【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!

最后: 可以在公众号:伤心的辣条 ! 免费领取一份216页软件测试工程师面试宝典文档资料。以及相对应的视频学习教程免费分享!,其中包括了有基础知识、Linux必备、Shell、互联网程序原理、mysql数据库、抓包工具专题、接口测试工具、测试进阶-Python编程、Web自动化测试、APP自动化测试、接口自动化测试、测试高级持续集成、测试架构开发测试框架、性能测试、安全测试等。

学习不要孤军奋战,最好是能抱团取暖,相互成就一起成长,群众效应的效果是非常强大的,大家一起学习,一起打卡,会更有学习动力,也更能坚持下去。你可以加入我们的测试技术交流扣扣群:914172719(里面有各种软件测试资源和技术讨论)

喜欢软件测试的小伙伴们,如果我的博客对你有帮助、如果你喜欢我的博客内容,请 “点赞” “评论” “收藏” 一键三连哦!


好文推荐

转行面试,跳槽面试,软件测试人员都必须知道的这几种面试技巧!

面试经:一线城市搬砖!又面软件测试岗,5000就知足了…

面试官:工作三年,还来面初级测试?恐怕你的软件测试工程师的头衔要加双引号…

什么样的人适合从事软件测试工作?

那个准点下班的人,比我先升职了…

测试岗反复跳槽,跳着跳着就跳没了…

今天终于把爬虫的Ajax请求搞懂了

今天终于把爬虫的Ajax请求搞懂了

一、案例分析及存在的问题

首先,我们是想要爬取http://www.fintechdb.cn/这个网站中的各个不同省份的一些数据,但是如果像普通的请求方式那样:(注意是不同省份的数据)

直接撸出代码来:

import requests
url = 'http://www.fintechdb.cn/request/loadmore'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36 Edg/91.0.864.41',
    # 'X-Requested-With': 'XMLHttpRequest'
}
data = {
    'csrf_weiyangx_token': 'a8c2eafab6bd8f2041b6c2e0c8a3811b',
    'city': '台湾省,四川省',
    'financing': '0',
    'field': '0',
    'timestart': '0',
    'timeend': '0',
    'offset': '0',
    'sort': '1',
    'order': 'desc'
}
res = requests.post(url=url, data=data, headers=headers)
print(res.status_code)
print(res)
print(res.content.decode())

好了,敲完代码,自己还以为万事大吉了,谁知道右击然后,点击运行:
结果一看,傻眼了;


我说:诶,真是奇怪了,我的请求不都是返回来了状态码 200 嘛?怎么给我一个Wrong啊?是不是他故意返回一个 200 ,让我以为请求成功了啊?

带着这些疑问,我打开了网页,点进去了我的那个网址,发现;

啊,原来网页本身的内容就是Wrong啊,看来是请求正确的啦。

那么,问题又来了,那那些请求的数据又是放在了哪里了呢?

明明是可以看到的啊

真的是邪门了啊???

二、问题的解决

后来,我查阅各种资料。。。。。。

最后发现,原来原因在于这个网站是用Ajax来写的,

Ajax简介

AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。

AJAX 不是新的编程语言,而是一种使用现有标准的新方法。

AJAX 是一种用于创建快速动态网页的技术。

总之一句话:
Ajax就是不需要重新加载页面就可以使得网页的一部分内容进行一定的更新,而 XMLHttpRequest 对象是实现Ajax的基础环节, XMLHttpRequest 对象对象是实现浏览器(Html)与数据进行交互的。

下面回到原本的 额问题

问题解决

我们重新进行一下网页的捕获,发现,诶,果然有一个 XMLHttpRequest 对象对象这个请求的头的参数

那好办,我们直接就把这个请求的参数也带进请求头里面去就好了,对不对?
代码如下:

import requests
url = 'http://www.fintechdb.cn/request/loadmore'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36 Edg/91.0.864.41',
    'X-Requested-With': 'XMLHttpRequest'
}
data = {
    'csrf_weiyangx_token': 'a8c2eafab6bd8f2041b6c2e0c8a3811b',
    'city': '台湾省,四川省',
    'financing': '0',
    'field': '0',
    'timestart': '0',
    'timeend': '0',
    'offset': '0',
    'sort': '1',
    'order': 'desc'
}
res = requests.post(url=url, data=data, headers=headers)
print(res.status_code)
print(res)
print(res.content.decode())

(这里其实就是比上一个代码多了一个请求头参数:
‘X-Requested-With’: ‘XMLHttpRequest’
然后就ok啦~)

果然,如我所愿,最终还是得到了我那梦寐以求的数据(^ _ ^)啦~:


反正呢,至少现在不是什么Wrong了啦。
然后你现在想要那个省份的就直接修改一下post请求就可以实现了啦,后面不用多说大家也都懂的。

三、总结

1、Ajax

Ajax前面结束过了,就是实现异步的js和xml的,Ajax的英文全程为:
Asynchronous JavaScript and XML
翻译一下;
AJAX = 异步 JavaScript 和 XML

就是说把网页的呈现和数据的存储分开来进行,js专门负责实行页面的呈现、调用其他的资源等功能,而xml呢,自己搞自己的数据存储以及传输 去吧,二者是异步的,就是说,他们之间是独立进行的额,彼此互不干扰,互不相干。

最后再说一遍:
Ajax请求:
AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。

2、XMLHttpRequest

为了实现Ajax这种技术,我们必须要有一定的基础的其他技术来作为支撑,所以就有了XMLHttpRequest对象的存在。XMLHttpRequest是为了实现异步的存储与传输等功能,当然,我们也可以通过一个网页的请求头是否有XMLHttpRequest来判断,这个网页是不是使用了Ajax技术呢。

3、解决问题

如果我们发现了这个网页使用Ajax来实现的话,那么,我们直接在请求头(headers)里面加入一个XMLHttpRequest的请求参数即就可以啦。

最后,感谢大家的阅读,希望对大家有一定的帮助了啦。

以上是关于职场人们天天说的接口Mock测试,今天我终于搞懂了的主要内容,如果未能解决你的问题,请参考以下文章

今天终于把爬虫的Ajax请求搞懂了

今天终于把爬虫的Ajax请求搞懂了

数据库数据仓库大数据,终于搞懂了。。

python单例模式你搞懂了么?我是终于懂了~

多次尝试学习,终于搞懂了微服务架构

终于搞懂了shell bash cmd...