【问题标题】:mock s3 connection and boto.S3key to check set_content_from_string method模拟 s3 连接和 boto.S3key 以检查 set_content_from_string 方法
【发布时间】:2017-04-22 07:41:17
【问题描述】:

我正在使用 python mock 进行单元测试。我浏览了与模拟相关的博客和 python 文档,但对模拟测试用例感到困惑。 这是我要为其编写测试用例的 sn-p。 议程是使用模拟测试方法“set_contents_from_string()”。

def write_to_customer_registry(customer):

    # establish a connection with S3
    conn = _connect_to_s3()

    # build customer registry dict and convert it to json
    customer_registry_dict = json.dumps(build_customer_registry_dict(customer))

    # attempt to access requested bucket
    bucket = _get_customer_bucket(conn)

    s3_key = _get_customer_key(bucket, customer)
    s3_key.set_metadata('Content-Type', 'application/json')
    s3_key.set_contents_from_string(customer_registry_dict)
    return s3_key

【问题讨论】:

    标签: python unit-testing mocking


    【解决方案1】:

    当您测试一些私有方法时,我已将它们添加到我称为 s3.py 的模块中,其中包含您的代码:

    import json
    
    def _connect_to_s3():
        raise
    
    def _get_customer_bucket(conn):
        raise
    
    def _get_customer_key(bucket, customer):
        raise
    
    def build_customer_registry_dict(cust):
        raise
    
    def write_to_customer_registry(customer):
    
        # establish a connection with S3
        conn = _connect_to_s3()
    
        # build customer registry dict and convert it to json
        customer_registry_dict = json.dumps(build_customer_registry_dict(customer))
    
        # attempt to access requested bucket
        bucket = _get_customer_bucket(conn)
    
        s3_key = _get_customer_key(bucket, customer)
        s3_key.set_metadata('Content-Type', 'application/json')
        s3_key.set_contents_from_string(customer_registry_dict)
        return s3_key
    

    接下来,在另一个模块 test_s3.py 中,我测试了您的代码,并考虑到对于单元测试,所有与第三方的交互,例如对 s3 的网络调用都应该修补:

    from unittest.mock import MagicMock, Mock, patch
    from s3 import write_to_customer_registry
    import json
    
    @patch('json.dumps', return_value={})
    @patch('s3._get_customer_key')
    @patch('s3.build_customer_registry_dict')
    @patch('s3._get_customer_bucket')
    @patch('s3._connect_to_s3')
    def test_write_to_customer_registry(connect_mock, get_bucket_mock, build_customer_registry_dict_mock, get_customer_key_mock, json_mock):
    
      customer = MagicMock()
      connect_mock.return_value = 'connection'
      get_bucket_mock.return_value = 'bucket'
      get_customer_key_mock.return_value = MagicMock()
    
      write_to_customer_registry(customer)
    
      assert connect_mock.call_count == 1
      assert get_bucket_mock.call_count == 1
      assert get_customer_key_mock.call_count == 1
    
      get_bucket_mock.assert_called_with('connection')
      get_customer_key_mock.assert_called_with('bucket', customer)
      get_customer_key_mock.return_value.set_metadata.assert_called_with('Content-Type', 'application/json')
      get_customer_key_mock.return_value.set_contents_from_string.assert_called_with({})
    

    正如您从测试中看到的那样,我没有测试set_contents_from_string 正在做应该做的事情(因为应该已经被 boto 库测试过),但是它是用正确的参数调用的。 如果您仍然怀疑 boto 库没有正确测试此类调用,您可以随时在 boto Githubboto3 Github 中自行检查

    您可以测试的其他一点是您正在正确处理代码中的不同异常和边缘情况。

    最后,您可以在docs 中找到有关修补和模拟的更多信息。通常关于where to patch 的部分非常有用。

    其他一些资源是这个 blog post 和 python mock gotchas 或者这个 blog post 我在 Stackoverflow 中回答了相关的 pytest、修补和模拟问题后写了自己(无耻的自我插件)。

    【讨论】:

      【解决方案2】:

      想出了对我有用的解决方案,在这里发布,可能对某人有帮助。

      def setup(self):
          self.customer = Customer.objects.create('tiertranstests')
          self.customer.save()
      
      def test_build_customer_registry(self):
          mock_connection = Mock()
          mock_bucket = Mock()
          mock_s3_key = Mock()
      
          customer_registry_dict = json.dumps(build_customer_registry_dict(self.customer))
          # Patch S3 connection and Key class of registry method
          with patch('<path>.customer_registry.S3Connection', Mock(return_value=mock_connection)),\
               patch('<path>.customer_registry.Key', Mock(return_value=mock_s3_key)):
      
              mock_connection.get_bucket = Mock(return_value=mock_bucket)
              mock_s3_key.set_metadata.return_value = None
              mock_s3_key.set_contents_from_string = Mock(return_value=customer_registry_dict)
      
              write_to_customer_registry(self.customer)
              mock_s3_key.set_contents_from_string.assert_called_once_with(customer_registry_dict)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-27
        • 1970-01-01
        • 2016-09-05
        • 1970-01-01
        相关资源
        最近更新 更多