【问题标题】:TestCase - Exception not raised in with statement when mocking __enter__TestCase - 模拟 __enter__ 时未在 with 语句中引发异常
【发布时间】:2017-04-12 12:22:40
【问题描述】:

我正在尝试测试一个包含 with 语句的 Python 方法。 with 语句中的代码可以引发RuntimeError。我所说的测试测试RuntimeError 是否被引发。

__enter____exit__ 方法很重(通常打开和关闭 SSH 连接),我在测试时模拟它们。

这是我要测试的方法的简化定义:

# client.py
class Client():
    def method_to_test():
        with self:
            raise RuntimeError()

为了清楚起见,我省略了__enter____exit__的定义,并删除了method_to_test中所有与当前问题无关的代码。

为了测试这个方法,我模拟了__enter____exit__,并检查RuntimeError 是否被提升:

# tests.py
from django.test import TestCase
import mock
from .client import Client

class ClientTestCase(TestCase):
    @mock.patch('mymodule.client.Client.__enter__')
    @mock.patch('mymodule.client.Client.__exit__')
    def test_method_raises_Runtime(self, mock_exit, mock_enter):
        mock_enter.return_value = None
        client = Client()
        with self.assertRaises(RuntimeError):
            client.method_to_test()

此测试失败:AssertionError: RuntimeError not raised

如果我不模拟 __enter__,则会引发 RuntimeError。为什么嘲笑 __enter__ 会使这个测试失败?

【问题讨论】:

  • 什么是mymodule?我不认为你嘲笑了正确的事情。
  • @chepner mymodule 是 client.py 和 tests.py 所在的模块。在使用pdb时,我清楚地看到self.__enter__self.__exit__类型是MagicMock,这意味着我在正确的地方打补丁。

标签: python django unit-testing mocking with-statement


【解决方案1】:

见于 PEP343 https://www.python.org/dev/peps/pep-0343/

The exception is swallowed if exit() returns true

由于self.__exit__Client.method_to_test 中的MagicMockself.__exit__ 返回一个MagicMock,评估为TrueRuntimeError 被吞了。

修复很简单。 self.__exit__() 返回 None 而不是 MagicMock

# tests.py
from django.test import TestCase
import mock
from .client import Client

class ClientTestCase(TestCase):
    @mock.patch('mymodule.client.Client.__enter__')
    @mock.patch('mymodule.client.Client.__exit__')
    def test_method_raises_Runtime(self, mock_exit, mock_enter):
        # __exit__ returns None, evaluated as False
        mock_exit.return_value = None
        mock_enter.return_value = None
        client = Client()
        with self.assertRaises(RuntimeError):
            client.method_to_test()

【讨论】:

    猜你喜欢
    • 2019-02-07
    • 1970-01-01
    • 1970-01-01
    • 2014-05-08
    • 2017-09-11
    • 1970-01-01
    • 2016-10-31
    • 2011-02-26
    • 2010-10-17
    相关资源
    最近更新 更多