单元测试-Mock Server

Mock Server

介绍

什么是mock?

mock是针对单元测试的一种应用,用于代替一些不易构造和获取的对象,已达到和真实对象同等的效果,这种应用可以很方便地解除单元测试中的各种依赖,降低编写单元测试的难度,提高工作效率。实现mock的技术可以分为两类:mock数据和mock服务

mock数据:即mock一个对象,写入一些预期值,通过它进行自己想要的测试。常见的有:EasyMock、Mockito、WireMock、JMockit,主要适用于单元测试

mock服务:即mock一个server,构造一个依赖的服务并给予他预期的服务返回值,适合集成测试,如moco框架

什么是mock server?

mock server是专门实现mock功能的一个服务,模拟其它团队/公司提供的相关服务的临时server

关于moco

moco是一个类似Mock的工具框架,一个简单搭建模拟服务器的程序库/工具,只需要简单配置request、response等即可满足要求,支持http、https、socket协议,支持在request中设置Headers、Cookies、StatusCode等,支持GET、POST、PUT、DELETE等请求方式;支持多种数据格式,如json、text、xml、file等;可与其它工具集成,如Junit、Maven等

只能模拟出简单的场景。如果接收到请求后需要做一些处理,如需查询数据库、进行运算、或者一些复杂的操作,就无能为力了

如何使用moco?

步骤一:

下载:https://github.com/dreamhead/moco

下拉找到Quick Start,点击 Standalone Moco Runner

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LIrMOaV3-1644474590739)(C:\Users\melot\AppData\Roaming\Typora\typora-user-images\image-20220209152339691.png)]

步骤二:

安装jdk,配置json文件,将下载好的moco的jar包与配置的json文件放置同一个文件夹路径下,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HreBpON8-1644474590743)(C:\Users\melot\AppData\Roaming\Typora\typora-user-images\image-20220209153248564.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cpepzkB2-1644474590744)(C:\Users\melot\AppData\Roaming\Typora\typora-user-images\image-20220209153312224.png)]

在该路径下打开cmd命令行,输入命令:

java -jar moco-runner-1.3.0-standalone.jar http -p 9090 -c test.json

此时相当于mock服务在我们本地9090端口上启动了,可通过浏览器进行访问:localhost:9090/test 访问查看

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V4CaxDLJ-1644474590745)(C:\Users\melot\AppData\Roaming\Typora\typora-user-images\image-20220209154749207.png)]

步骤三:配置不同的请求

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-24DSkpf1-1644474590750)(C:\Users\melot\AppData\Roaming\Typora\typora-user-images\image-20220209161910163.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1QSltv2j-1644474590753)(C:\Users\melot\AppData\Roaming\Typora\typora-user-images\image-20220209161517176.png)]

[{
	"description":"test demo",
	"request":
	{
		"uri":{
            "startswith":"/tes", # 以tes开头
            "endsWith":"t", # 以t结尾
            "contain":"test" # 包含test
        },
		"method":"PUT",
		"headers":{
			"Content-Type":"application/xml"
		}
		"queries":{
			"key1":"abc",
			"key2":"123"
		}
	},
	"response":
	{
		"headers":{
			"Content-Type":"application/json"
		},
		"status":200,
		"cookies":{
            "login":"true"
        }
		"text":{
            "template":"${req.queries['name']}"  # 动态返回参数值
        },
		"redirectTo":"http://www.baidu.com" # 重定向到百度
		"latency":{    # 延迟
        	"duration":1,
            "unit":"second"
        }

	}
}]

Event事件:请求一些特定接口的时候,需要去请求别的地址,从而才能完成请求。
例如OAuth等,牵涉到第三方的情况

 {
    "request": {
        "uri" : "/event"
    },
    "response": {
        "text": "event"
    },
    "on": {
        "complete": {
            "get" : {
                "url" : "http://another_site/OAuth?xxx=xxxx"
            }
        }
    }
}

分模块:当我们访问
http://localhost:12306/user/create 和 http://localhost:12306/todo/getAll时候,
会跳到后面对应的json再处理一遍

[ 
    {
    "context": "/user", "include": "user.json" 
    },
    { 
     "context": "/todo", "include": "todo.json"  
    }
]

//user
[ { "request" : { "uri" : "/create" }, "response" : { "text" : "这是创建用户请求" } } ]
//todo
[ { "request" : { "uri" : "/getAll" }, "response" : { "text" : "这是获取用户所有Todo的请求" } } ]

Moco支持在全局的配置文件中引入其他配置文件,这样就可以分服务定义配置文件,便于管理。
配置好文件,在全局文件中引入即可:
全局配置如下:

java -jar moco-runner-standalone.jar start -p 5638 -g data.json

python中mock的使用

python3中,mock已经被集成到了unittest单元测试框架中,所以可以直接使用

function.py

def add_and_multiply(x,y):
    addition = x + y
    multiple = multiply(x,y)
    return addition,multiple

def multiply(x,y):
    return x * y

func_test.py

import unittest
from unittest import mock
from unittest.mock import patch

from test_mock import function


class MyTestCase(unittest.TestCase):
    # 正常用例
    def test_add_and_multiply(self):
        x = 3
        y = 5
        addition,multiple = function.add_and_multiply(x,y)
        self.assertEqual(8,addition)
        self.assertEqual(15,multiple)

    # multiply函数不可用时
    # patch()装饰/上下文管理区,模拟类或对象在模块测试,在测试过程中,指定的对象将被替换成为一个模拟,并在测试结束时还原
    @patch("test_mock.function.multiply")
    def test_add_and_multiply2(self,mock_multiply):
        x = 3
        y = 5
        # 设定mock_multiply的返回值固定为15
        mock_multiply.return_value = 15
        addition,multiply = function.add_and_multiply(x,y)
        # 校验mock_multiply方法的参数是否正确
        mock_multiply.assert_called_once_with(3,5)
        self.assertEqual(8,addition)
        self.assertEqual(15,multiply)

    # 执行真实函数
    def test_add_and_multiply3(self):
        x = 3
        y = 5
        # 若存在side_effect参数值,则该参数值覆盖return_value
        function.multiply = mock.Mock(return_value=1,side_effect=function.multiply)
        result = function.multiply(3,5)
        print(result)
        self.assertEqual(result,15)


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

你可能感兴趣的:(测试工具的使用,单元测试,python)