How to use python mock library and decorator with unittest lib?
我正在尝试使用模拟python库,并决定使用装饰器来隐藏一些重复操作,以便使用相应的替换方法设置模拟side_effect变量。
到目前为止,我有以下代码,它没有进入测试,它基本上什么也没做。 有想法该怎么解决这个吗? 谢谢!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | 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 |
确保替换执行命名空间中的函数。 根据导入,您当前的代码可能会或可能不会替换您认为它正在替换的内容。 以下是我认为您试图做的事情。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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() |
但是,您可能更成功地更换了get& 发布自动指定的MagicMock对象。 如果这对您不起作用,请使用您自己的自定义替换。
例如,如果您知道"get"调用的顺序,则以下补丁装饰器将起作用。
1 2 3 4 5 | 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而不是编写自己的返回生成函数。