3

我正在尝试使用模拟 python 库,并决定使用装饰器来隐藏一些重复操作,以使用相应的替换方法设置模拟副作用变量。

到目前为止,我有以下代码,它没有进入测试,它基本上什么都不做。有想法该怎么解决这个吗?谢谢!

import unittest
from mock import patch

# Replacement method for requests.get call
def mock_requests_get(url=None, **kwargs):
    if url == URL1:
        return {'url':url, 'status_code':200, 'status':'success'}

    if url == URL2: A
        return {'url':url, 'status_code':403}

# Replacement method for requests.post call
def mock_requests_post(url, data=None, **kwargs):
    if url == URL1 and data['data']=='go':
        return {'url':url, 'status_code':200, 'status':'success'}

    if url == URL2 and data['data']!='gogo':
        return {'url':url, 'status_code':403}

# Decorator which sets mock replacement methods
def mock_type(method=''):
    def _mock(func):
        def _decorator(mock_get, mock_post, *args, **kwargs):
            print method
            if method == 'GET':
                mock_get.side_effect = mock_requests_get
            if method == 'POST':
                mock_post.side_effect = mock_requests_post
            func(mock_get, mock_post, *args, **kwargs)
        return _decorator
    return _mock

@patch('requests.post')
@patch('requests.get')
class TestKeywordsApi(unittest.TestCase):

    def setUp(self):
        self.ka = KeywordsApi()

    @mock_type('GET')
    def test_get(self, mock_get, mock_post):
        # Replace this code in mock_type decorator:
        #mock_get.side_effect=mock_requests_get

        print self.ka.get(URL1)
        print self.ka.get(URL2)

        # Do asserts

    @mock_type('POST')
    def test_post(self, mock_get, mock_post):
        # Replace this code in mock_type decorator:
        #mock_post.side_effect=mock_requests_post

        print self.ka.post(URL1, {'data':'go'})
        print self.ka.post(URL2, {'data':'go'})

        # Do asserts
4

1 回答 1

2

确保替换执行命名空间中的函数。根据导入,您当前的代码可能会或可能不会替换您认为它正在替换的内容。以下是我相信您正在尝试做的事情。

import kwmodule
import unittest, mock

def mock_requests_get(url=None, **kwargs):
    "Replacement method for requests.get call"
    pass

def mock_requests_post(url, data=None, **kwargs):
    "Replacement method for requests.post call"
    pass

@mock.patch('kwmodule.requests.post', mock_requests_post)
@mock.patch('kwmodule.requests.get', mock_requests_get)    
class TestKeywordsApi(unittest.TestCase):
     def setUp(self):
         self.ka = kwmodule.KeywordsApi()

但是,使用自动指定的 MagicMock 对象替换 get 和 post 可能会更成功。如果这对您不起作用,请使用您自己的自定义替换。

例如,如果您知道“get”的调用顺序,则以下补丁装饰器将起作用。

return_values = [{'url':url, 'status_code':200, 'status':'success'}, 
                 {'url':url, 'status_code':403}, 
                 AssertionError('Unexpected call.')]

@mock.patch('kwmodule.requests.get', autospec=True, side_effect=return_values)

这将在第一次调用时返回“成功”条件,第二次返回错误,如果第三次调用,则会引发 AssertionError。十分之九,我使用 side_effect 而不是编写自己的返回生成函数。

于 2012-12-15T23:50:46.603 回答