【问题标题】:How to use python mock library and decorator with unittest lib?如何将 python 模拟库和装饰器与 unittest 库一起使用?
【发布时间】:2012-09-01 03:56:30
【问题描述】:

我正在尝试使用mock python库,并决定使用装饰器来隐藏一些重复操作,用于设置mock side_effect vars和相应的替换方法。

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

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

【问题讨论】:

    标签: python unit-testing mocking decorator


    【解决方案1】:

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

    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 而不是自己编写返回生成函数。

    【讨论】:

      猜你喜欢
      • 2016-09-12
      • 2021-04-19
      • 1970-01-01
      • 2012-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多