如何在单元测试中使用python Mock side_effect作为Class方法

con*_*man 6 python unit-testing mocking

我在python中测试一个自定义API来发出http请求,但我不希望每次运行单元测试时都向真实的外部系统发出请求.我正在使用带有side_effect函数的python模拟库来动态伪造API响应.如何让side_effect方法像类方法一样?

import requests

class MyApiClass():
    def make_request(self, params):
        return requests.get('http://someurl.com', params=params)

    def create_an_object(self, params):
        return self.make_request(params)
Run Code Online (Sandbox Code Playgroud)
import unittest, mock

def side_effect_func(self, params):
    if params['name'] == 'Specific Name':
        return {'text': 'Specific Action'}
    else:
        return {'text': 'General Action'}

class MyApiTest(unittest.TestCase):
    def setUp(self):
        super(MyApiTest, self).setUp()
        mocked_method = mock.Mock(side_effect=side_effect_func)
        MyApiClass.make_request = mocked_method

    def test_create_object(self):
        api = MyApiClass()
        params = {'name': 'Specific Name'}
        r = api.create_an_object(params) # Complains that two arguments are needed!
        self.assertEqual(r['text'], 'Specific Action')
Run Code Online (Sandbox Code Playgroud)

我收到这个错误

TypeError: side_effect_func() takes exactly 2 arguments (1 given)
Run Code Online (Sandbox Code Playgroud)

但我想作为第一个论点side_effect_func传递api.感谢任何帮助!

Sil*_*Ray 4

最简单的方法可能是让您的模拟方法采用单个参数,然后MyApiClass在模拟方法本身中静态引用。partial否则,您可以尝试模拟类对象本身(基本上是制作模拟元类),或者可能使用用于动态构建模拟类方法的工厂。但是,如果单个参数/静态引用方法适合您,那对我来说似乎是最好的。

另外,从 Mock 文档中,可以使用 patch 来模拟未绑定的方法,这看起来可能更符合您的需要。