【问题标题】:MagicMock object evaluates to FalseMagicMock 对象的计算结果为 False
【发布时间】:2021-08-09 13:32:18
【问题描述】:

我有一个这样的 Python 类:

class MyClass:
  def __init__(self, client=None):
    self._client = client or Client()

  def encode(self, **kwargs):
    encoded = self._client.encode(**kwargs)
    [...]

所以这里的模式是MyClass 可以使用在初始化期间指定的Client。如果没有指定,构造函数会初始化一个新的Client 对象。

我想测试这个类,传递一个模拟的Client 实例:

with patch("Client", autospec=True) as mock_client:
    my_class = MyClass(client=mock_client)
    my_class.encode()
    [...]

我注意到,与预期不同的是,MyClass.__init__() 中初始化了一个新的 client 对象。 调试时,原来是因为被模拟的客户端评估为False

bool(mock_client)
False

我实际上可以像这样重写我的构造函数以使其按预期工作:

self._client = Client() if client is None else client

但这似乎更麻烦。为什么bool(mock_client) 计算结果为Falsemock_client is NoneTrue,这也令人困惑。

documentation about Boolean expressions in Python 声明如下:

以下值被解释为 false:False、None、所有类型的数字零以及空字符串和容器(包括字符串、元组、列表、字典、集合和冻结集)。所有其他值都被解释为 true

我不明白为什么 MagicMock 对象应该根据这个定义评估为 False

当我像这样创建模拟对象时,它确实评估为True

mock_client = patch("Client", autospec=True)

bool(mock_client) # -> True

然而,在这种情况下,模拟的客户端似乎缺乏规范,所以我收到了这个错误:

E       AttributeError: '_patch' object has no attribute 'encode'

使用patch 作为上下文管理器的第一种方法更可取,并由the documentation 推荐。它似乎也符合我的预期,只是它的计算结果为False

有没有办法在不更改我的代码的情况下处理这个问题?我发现if client is None Client() else clientclient or Client() 可读性差很多。

此外,我完全不明白为什么 bool(mock_client) 的计算结果为 False。这是unittest.mock 中的错误还是功能?

【问题讨论】:

  • 您想要一个模拟客户端,但您在 MyClass 上使用 patch。你不想给Client打补丁吗?
  • @Kyle 你是对的,这是一个复制粘贴错误。固定。

标签: python unit-testing nonetype


【解决方案1】:

检查无更好,因为这是确切的默认值。否则,您需要确保客户端永远不会评估为假,例如,如果它有一个长度或它自己的布尔值。不过,如果没问题的话……

您传递的模拟必须像您提供的文档链接一样提供 encode() 函数。但是您似乎在嘲笑您正在测试的课程。 (此外,据我所知,上下文管理器 mock_client 确实评估为 True。)

在您的示例中,您要测试什么 - 是否调用了客户端? self._client.encode(**kwargs) 运行的 IE?在这种情况下,一个简单的 magicmock 就可以了:

mock_client = unittest.mock.Mock()
myclass = MyClass(client=mock_client)
myclass.encode(xxx=1, yyy=2)
mock_client.encode.assert_called_once()
mock_client.encode.assert_called_with(xxx=1, yyy=2)

【讨论】:

  • 确实看起来更好,但仅在使用mock_client = MagicMock() 时。使用Mock(),当进一步处理encode() 结果时,我的代码会遇到RuntimeError。
  • 在您的 sn-p 中,您不使用 encode() 调用的任何返回值。如果需要,您可以让 mock 提供返回数据或创建副作用。
  • 没错,我应该包含更多实际的编码功能。它继续处理客户端响应。它们的内容对测试无关紧要,但它们的类型很重要。这适用于 MagicMock。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-12
  • 2018-03-08
  • 1970-01-01
  • 2020-12-10
  • 2015-05-28
  • 2022-01-25
  • 1970-01-01
相关资源
最近更新 更多