【问题标题】:Django unittest and mocking the requests moduleDjango unittest 和模拟请求模块
【发布时间】:2013-08-02 18:02:47
【问题描述】:

我是 Mock 新手,正在为此功能编写单元测试:

# utils.py
import requests    

def some_function(user):
    payload = {'Email': user.email}
    url = 'http://api.example.com'
    response = requests.get(url, params=payload)      

    if response.status_code == 200:
       return response.json()
    else:
        return None

我在单元测试中使用Michael Foord's Mock 库,并且在模拟response.json() 以返回json 结构时遇到了困难。这是我的单元测试:

# tests.py
from .utils import some_function

class UtilsTestCase(unittest.TestCase):
    def test_some_function(self):
        with patch('utils.requests') as mock_requests:
            mock_requests.get.return_value.status_code = 200
            mock_requests.get.return_value.content = '{"UserId":"123456"}'
            results = some_function(self.user)
            self.assertEqual(results['UserId'], '123456')

在阅读文档后,我尝试了多种不同模拟设置的组合,但没有成功。如果我在单元测试中打印results,它总是显示以下内容,而不是我想要的 json 数据结构:

<MagicMock name=u'requests.get().json().__getitem__().__getitem__()' id='30315152'>

想到我做错了什么?

【问题讨论】:

    标签: python unit-testing mocking python-requests


    【解决方案1】:

    修补 json 方法而不是 content。 (content 没有在some_function 中使用)

    试试下面的代码。

    import unittest
    
    from mock import Mock, patch
    
    import utils
    
    class UtilsTestCase(unittest.TestCase):
        def test_some_function(self):
            user = self.user = Mock()
            user.email = 'user@example.com'
            with patch('utils.requests') as mock_requests:
                mock_requests.get.return_value = mock_response = Mock()
                mock_response.status_code = 200
                mock_response.json.return_value = {"UserId":"123456"}
                results = utils.some_function(self.user)
                self.assertEqual(results['UserId'], '123456')
    

    【讨论】:

    • 非常感谢您的回答。它现在按我希望的那样工作。
    • 我要添加到您的单元测试中的另一个断言测试是确保使用预期参数调用 request.get 方法。类似mock_get.assert_called_with('http://api.example.com', payload={'Email': self.user.email}。这可以确保您的库代码使用预期的参数进行请求调用,这与测试库代码的返回值一样重要,这是模拟的。
    【解决方案2】:

    我喜欢使用的另一个更可重用的模式是在单元测试的setUp 方法中启动修补程序。检查是否使用预期参数调用了模拟请求也很重要:

    class UtilsTestCase(TestCase):
    
        def setUp(self):
            self.user = Mock(id=123, email='foo@bar.com')
    
            patcher = patch('utils.requests.get')
            self.mock_response = Mock(status_code=200)
            self.mock_response.raise_for_status.return_value = None
            self.mock_response.json.return_value = {'UserId': self.user.id}
            self.mock_request = patcher.start()
            self.mock_request.return_value = self.mock_response
    
        def tearDown(self):
            self.mock_request.stop()
    
        def test_request(self):
            results = utils.some_function(self.user)
    
            self.assertEqual(results['UserId'], 123)
    
            self.mock_request.assert_called_once_with(
                'http://api.example.com'
                payload={'Email': self.user.email},
            )
    
        def test_bad_request(self):
            # override defaults and reassign
            self.mock_response.status_code = 500
            self.mock_request.return_value = self.mock_response
            results = utils.some_function(self.user)
    
            self.assertEqual(results, None)
    
            self.mock_request.assert_called_once_with(
                'http://api.example.com'
                payload={'Email': user.email},
            )
    

    【讨论】:

      【解决方案3】:

      我认为另一种更清晰直接的方式:

      import unittest
      
      from mock import Mock, patch
      
      import utils
      
      class UtilsTestCase(unittest.TestCase):
          def test_some_function(self):
              mock_response = Mock()
              mock_response.status_code = 200
              mock_response.json.return_value = {"UserId": "123456"}
              with patch('utils.requests.get') as mock_requests:
                  results = utils.some_function(self.user)
                  self.assertEqual(results['UserId'], '123456')
      

      【讨论】:

        猜你喜欢
        • 2013-04-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-25
        • 1970-01-01
        • 2012-03-11
        • 1970-01-01
        • 2018-02-24
        相关资源
        最近更新 更多