Mock测试是什么?

一.Mock概念

mock 的意思是模拟,也就是模拟接口返回的信息,用已有的信息替换它需要返回的信息,从实现对上级模块的测试。
这里分为两类测试:一类是前端对接口的mock,一类是后端单元测试中涉及的mock

单纯的前端mock可以通过抓包工具Fiddler,Charles实现,通过修改代理返回的数据,实现多种场景的测试。这里在抓包工具之中会解释。

后端的Mock则是从接口的角度,如果一个接口A返回的数据需要依赖于另一个接口B,当敏捷开发中B接口还未开发完全时候这里会需要用到Mock。

在python3.0中mock模块已经被集成到unittest里面。

参考:
https://www.cnblogs.com/fnng/p/5648247.html
参考:https://docs.python.org/3/library/unittest.mock.html
参考:
http://engineroom.trackmaven.com/blog/making-a-mockery-of-python/

二.实现方式

1.借助一个mock服务平台

easymock

2.借助已有的框架
  • java ->
  • python -> unittest.mock

三.举一个栗子

定义一个Mock类
  • class Mock(spec=None,side_effect=None,return_value=DEFAULT,name=None)
  • spec:定义Mock对象的属性值,可以是一个列表,字符串,一个对象的实例
  • side_effect:可以用来抛出异常或者动态改变返回值,可以覆盖return_value
  • return_value:定义mock的返回值
  • name:作为mock对象的标识可以在print时候看到
简单的demo

这里我们需要测试的是一个Count类里面的add函数,但是这个函数还没有写出来.

  • count
'''这是一个计算类'''
class Count(object):
    def add(self):
        pass
  • test_count
'''这里要测试这个计算类'''
from unittest import mock
import unittest
from API_Mock.count import Count

class TestCount(unittest.TestCase):
    def test_add(self):
        mycount = Count()
        add_value = 13
        #这里mock了mycount类里面add函数的返回结果等于13
        mycount.add = mock.Mock(return_value=add_value)
        #这里相当于正常调用add函数
        result = mycount.add(8,5)
        #使用断言判断返回的结果是否和mock的相等
        self.assertEqual(result,add_value)

if __name__ == '__main__':
    unittest.main()

输出结果:

Ran 1 test in 0.000s

OK

Process finished with exit code 0
完成功能部分
  • count
'''这是一个计算类'''
class Count(object):
    def add(self, a, b):
        return a + b 
  • test_count
'''这里要测试这个计算类'''
from unittest import mock
import unittest
from API_Mock.count import Count

class TestCount(unittest.TestCase):

    def test_add(self):
        mycount = Count()
        add_value = 13
        #这里使用side_effect参数覆盖了return_value的结果。
        mycount.add = mock.Mock(return_value=add_value , side_effect=mycount.add)

        #这里真正调用add方法并打印结果
        result = mycount.add(8,8)
        print(result)

        #检查mock方法是否获得了正确的参数
        mycount.add.assert_called_with(8,8)
        self.assertEqual(result, 16)
        
        
if __name__ == '__main__':
    unittest.main()
解决测试依赖

上面只是针对单独的模块进行测试,假设我们测试的A模块需要B模块返回的数据作为前提,如果B模块返回的结果错误,也会导致A模块的测试失败。这里也需要mock来模拟B模块的返回。

1.原先模块
  • count
'''这是一个计算类'''
class Count(object):
    def add(self, a, b):
        return a + b

    def mutiply(self,a,b):
        return a*b

    def add_and_mutiply(self,a,b):
        addition = self.add(a,b)
        mutiple = self.mutiply(a,b)
        return (addition,mutiple)
  • test_count
'''这里要测试这个计算类'''
from unittest import mock
import unittest
from API_Mock.count import Count

class TestCount(unittest.TestCase):

    def test_add_and_mutiply(self):
        mycount = Count()
        x = 3
        y = 5
        addition,mutiple = mycount.add_and_mutiply(x,y)
        self.assertEqual(8,addition)
        self.assertEqual(15,mutiple)


if __name__ == '__main__':
    unittest.main()
2.依赖项缺失

当依赖项缺失的时候,也就是模块B返回错误,这里依然要保证对模块A的测试是正常的。

这里给add函数返回结果+3

class Count(object):
    def add(self, a, b):
        return a + b+3

所以,会有以下报错

  • 报错
Ran 1 test in 0.000s
FAILED (failures=1)

11 != 8
Expected :8
Actual   :11

测试用例运行失败,但是实际上模块A并没有任何改动,这里就需要mockB模块

  • test_count
'''这里要测试这个计算类'''
from unittest import mock
import unittest
from API_Mock.count import Count
from unittest.mock import patch

class TestCount(unittest.TestCase):
    def test_add_and_mutiply(self):
        mycount = Count()
        x = 3
        y = 5
        mycount.add = mock.Mock(return_value = 8)
        addition,mutiple = mycount.add_and_mutiply(x,y)

        mycount.add.assert_called_with(3,5)

        self.assertEqual(8,addition)
        self.assertEqual(15,mutiple)


if __name__ == '__main__':
    unittest.main()

<think>我们首先从用户的问题出发,用户询问的是mock的含义以及在JSONPath断言失败场景中的作用。结合之前的对话历史,用户之前遇到了JSONPath断言失败的问题,现在想了解mock如何在这种场景下发挥作用。根据引用[1]中提到的一些测试概念(如pytest插件、并发执行、重跑机制等),我们可以推测用户是在自动化测试的语境下讨论问题。同时引用[3]提到了测试目的和软件质量,引用[4]提到了JUnit测试步骤和断言,这些都与测试相关。因此,我们定义mockMock(模拟)是一种在软件测试中隔离依赖组件的技术。当测试一个对象时,如果它依赖其他难以控制或访问的组件(如数据库、网络服务等),我们可以创建这些依赖的模拟对象来代替真实对象。这样可以让测试更聚焦于被测试对象的行为,而不受外部依赖的影响。在JSONPath断言失败场景中,mock的作用主要体现在:1.隔离外部依赖:当被测接口依赖于其他服务时,使用mock模拟这些服务的返回值,确保每次测试的输入数据可控。2.模拟异常场景:通过mock模拟返回错误码(如500)的响应,从而触发JSONPath断言失败,用于验证断言逻辑的正确性。3.加速测试执行:避免了真实网络调用,使得测试更快。具体到JSONPath断言失败的问题,mock可以:-在开发阶段,提前模拟各种响应(包括异常响应)来编写和调试断言。-当断言失败时,通过mock确保返回的数据是预设的(如固定返回500),从而排除外部服务不稳定导致的问题。回答结构:1.解释mock的概念(结合引用[1]和[4]的测试背景)。2.详细说明mock在JSONPath断言失败场景中的应用(结合用户之前遇到的断言失败问题)。3.给出一个简单的示例,展示如何用mock模拟返回500状态码,然后进行JSONPath断言。4.总结mock的优势。示例部分可以选择一个具体的测试框架(如Python的unittest.mock或Java的Mockito)来演示,但考虑到用户之前的问题是在JMeter(Java)环境中,我们可以用Java的Mockito为例,但用户也可能使用其他语言,所以抽象描述。同时,根据引用[1]中提到的pytest插件,我们也可以提一下Python中如何使用mock。最后,生成相关问题。注意:由于引用[2]是关于JavaEE的,与当前问题关联不大,可以不使用。我们开始构建答案:</think> ### Mock的概念及其在JSONPath断言失败中的作用 #### 1. **Mock的定义与核心用途** Mock(模拟对象)是一种测试替身技术,用于隔离被测试代码与外部依赖(如API、数据库、文件系统等)。它允许开发者: - 创建可控的**预定义返回值**,替代真实依赖的响应 - 验证**调用参数**和**调用次数**是否符合预期 - 强制触发**异常或错误状态**(如500错误) - 解决测试环境不稳定或依赖项不可用的问题[^1][^4] 尤其在JSONPath断言场景中,mock可精确控制API返回的JSON结构,确保断言逻辑可靠验证。 #### 2. JSONPath断言失败时Mock的应用 当JSONPath断言`$.code not matches 500`失败时,mock可通过以下方式帮助问题排查: **① 隔离第三方依赖问题** ```python # Python示例:使用unittest.mock模拟API返回500错误 from unittest.mock import patch @patch('api_client.get_data') def test_json_assertion(mock_get): # 强制模拟API返回500状态码 mock_get.return_value = {"code": 500, "error": "Internal Error"} response = api_client.get_data() assert response["code"] != 500 # 验证断言逻辑是否准确捕获500 ``` **② 动态构造异常场景** ```java // Java示例:使用Mockito模拟嵌套JSON异常 @Mock ExternalService externalService; @Test public void testNestedJsonPath() { // 构造深度嵌套的JSON结构 Map<String, Object> nestedJson = Map.of( "response", Map.of("code", 500, "details", "DB_CONNECTION_FAILED") ); when(externalService.call()).thenReturn(nestedJson); Response res = testModule.processRequest(); // 验证JSONPath能否正确提取嵌套字段 assertNotEquals(500, JsonPath.read(res.body(), "$.response.code")); } ``` **③ 验证断言配置正确性** 通过对比真实响应与模拟响应: - 当**真实API返回500但断言失败** → JSONPath表达式错误 - 当**mock返回500但断言通过** → 断言逻辑反向错误(可能需要勾选*Invert Assertion*) - 当**两者行为一致** → 被测业务逻辑缺陷[^1] #### 3. Mock框架选择建议 | 语言/场景 | 推荐框架 | JSONPath相关功能 | |------------------|----------------------|--------------------------------| | **Java** | Mockito + JSONAssert | 支持深度JSON结构和路径验证[^4] | | **Python** | unittest.mock | 内置动态JSON对象构造 | | **JMeter** | JSR223 + Groovy | 结合`JsonSlurper`解析响应 | | **前端测试** | Jest + axios-mock | 拦截AJAX请求并返回模拟JSON | #### 4. Mock的核心优势 1. **确定性测试**:100%复现500错误等异常状态 2. **执行效率**:避免网络延迟影响测试速度 3. **逻辑验证**:独立验证JSONPath提取与业务处理逻辑 4. **安全隔离**:避免对生产数据库/API的误操作[^3] > **关键结论**:Mock不是JSONPath断言失败的解决方案,而是问题复现和逻辑验证的工具。它帮助区分到底是: > ✓ JSONPath表达式错误 > ✓ 断言配置错误 > ✓ 业务逻辑缺陷 > ✓ 环境依赖问题[^1][^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值