【问题标题】:AttributeError on Mocked Class in PythonPython中模拟类的AttributeError
【发布时间】:2021-10-06 20:39:12
【问题描述】:

我正在使用 mockito 对 Python 中的程序进行单元测试。我有一个像这样的课程:

import boto3
import datetime

class Cache:

    def __init__(self):
        client = boto3.resource('s3')
        self.bucket_name = 'name'
        self.bucket = client.Bucket(self.bucket_name)

    def setup_cache(self, cache_file='cache.csv', cache_filepath='cache'):
        cache_object = self.bucket.Object(cache_file)

        if cache_object.last_modified < datetime.datetime.now():
            self.bucket.download_file(cache_filepath, cache_file)
        else:
            print('Cache already up to date')


def main():
    cache = Cache()
    cache.setup_cache()

我遇到的测试代码是这样的:

from mockito import mock, when
import datetime
import boto3

import mock_cache

class TestMockCache:

    def test_last_mod(self):

        mock_client = mock()
        when(boto3).resource('s3').thenReturn(mock_client)

        mock_bucket = mock()
        when(mock_client).Bucket('name').thenReturn(mock_bucket)

        mock_bucket.last_modified = datetime.datetime.now()

        mock_cache.main()

在单元测试上运行 pytest 时,我收到了这个属性错误:

AttributeError: 'NoneType' object has no attribute 'last_modified'

从文档看来,我可以像这样分配“cache_mock.last_modified”。不过,我也试过:

when(cache_mock).last_modified.thenReturn(test_date)

得到:

AttributeError: 'StubbedInvocation' object has no attribute 'thenReturn'

我不完全理解,但假设这意味着 mockito mock() 对象不能有多个返回值?

对此的任何帮助将不胜感激。我觉得我误解了关于 mockito 的模拟如何工作或一般模拟的一些基本知识。

【问题讨论】:

  • 您能生成实时代码示例来重现问题吗?还请指定您尝试使用的 some_cache_library?
  • @Roxy 编辑了代码。 'some_cache_library' 只是一个虚构的东西。这里真正起作用的库是 boto3
  • 预期相同。我已经更新了下面的答案。如果您仍然无法解决,请告诉我。
  • 您是否能够通过以下解决方案?
  • 谢谢!那行得通。

标签: python unit-testing mocking mockito attributeerror


【解决方案1】:

来自Mockpatch 可用于模拟来自boto3client。不必从客户端返回任何东西,因为它被整体模拟了。

例如:

from folder.file import your_func
from unittest.mock import patch

class TestSomething(unittest.TestCase):
    @patch("botocore.client.BaseClient._make_api_call")
    def test_something(self, _mock_client_boto3):
        your_func()
        .. do something

如果你想从客户端返回一些东西,可以通过在补丁中指定return_value来实现,如下所示:

from folder.file import your_func
from unittest.mock import patch

class TestSomething(unittest.TestCase):
    @patch("botocore.client.BaseClient._make_api_call", return_value=None)
    def test_something(self, _mock_client_boto3):
        your_func()
        .. do something

【讨论】:

  • 这不是一个好的答案,因为它 a) 不使用 mockito 和 b) 修补了一个 private 方法。用户应该模拟出她使用的确切方法。我怎么知道_make_api_call 现在或将来是正确的?
猜你喜欢
  • 1970-01-01
  • 2019-02-27
  • 2017-08-31
  • 2023-04-06
  • 1970-01-01
  • 2016-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多