使用Python中的mock比较json.dumps返回的dict

时间:2017-02-09 17:39:17

标签: python unit-testing mocking python-requests

我的python工具“Bar”必须从某个服务器获取密钥。它使用requests.post方法。我想编写单元测试,它将检查是否使用正确的参数调用post。以下是测试的结果:

@mock.patch('bar_project.bar.main.requests.post')
def test_correct_request_call(self,
                              mock_requests_post):

    client = Bar.Bar(t_url, t_user_name, t_user_password)

    expected_call_args = ({'data': '{"password": "t_user_password", "username": "t_user_name"}',
                           'headers': {'Content-type': 'application/json'},
                           'url': 't_url/apilogin',
                           'verify': False})

    mock_requests_post_call_kwargs = mock_requests_post.call_args[1]
    self.assertEqual(mock_requests_post_call_kwargs, expected_call_args)

事情是,有50%的机会可以通过测试。这不是确定性的。有时mock_requests_post.call_args[1]会返回带data值的字典:

'{"username": "t_user_name", "password": "t_user_password"}'
有时候用 '{"password": "t_user_password", "username": "t_user_name"}'

如何重写测试以保持简单,但仍然检查我称为post的参数?

1 个答案:

答案 0 :(得分:0)

正如@jonrsharpe建议的那样,我使用json.loads通过加载dict返回的字符串来创建新的requests.post,然后将其与其他参数比较进行比较。现在每次测试通过。

@mock.patch('slot_project.Slot.main.requests.post')
def test_correct_request_call(self,
                              mock_requests_post):

    slot_client = Slot.Slot(t_url, t_user_name, t_user_password)

    mock_requests_post_call_kwargs = mock_requests_post.call_args[1]

    self.assertEqual(json.loads(mock_requests_post_call_kwargs['data']),
                     {"username": "t_user_name", "password": "t_user_password"})
    self.assertEqual(mock_requests_post_call_kwargs['headers'], {'Content-type': 'application/json'})
    self.assertEqual(mock_requests_post_call_kwargs['url'], 't_url/apilogin')
    self.assertFalse(mock_requests_post_call_kwargs['verify'])