断言 __init__ 是用正确的参数调用的
Asserting that __init__ was called with right arguments
我正在使用 python 模拟来断言特定对象是使用正确的参数创建的。这是我的代码的样子:
class Installer:
def __init__(foo, bar, version):
# Init stuff
pass
def __enter__(self):
return self
def __exit__(self, type, value, tb):
# cleanup
pass
def install(self):
# Install stuff
pass
class Deployer:
def deploy(self):
with Installer('foo', 'bar', 1) as installer:
installer.install()
现在,我想断言 installer
是用正确的参数创建的。这是我目前的代码:
class DeployerTest(unittest.TestCase):
@patch('Installer', autospec=True)
def testInstaller(self, mock_installer):
deployer = Deployer()
deployer.deploy()
# Can't do this :-(
mock_installer.__init__.assert_called_once_with('foo', 'bar', 1)
这是我得到的错误:
File "test_deployment.py", line .., in testInstaller
mock_installer.__init__.assert_called_once_with('foo', 'bar', 1)
AttributeError: 'function' object has no attribute 'assert_called_once_with'
这是固定代码(称之为test.py
)。谢谢大家!
import unittest
from mock import patch
class Installer:
def __init__(self, foo, bar, version):
# Init stuff
pass
def __enter__(self):
return self
def __exit__(self, type, value, tb):
# cleanup
pass
def install(self):
# Install stuff
pass
class Deployer:
def deploy(self):
with Installer('foo', 'bar', 1) as installer:
installer.install()
class DeployerTest(unittest.TestCase):
@patch('tests.test.Installer', autospec=True)
def testInstaller(self, mock_installer):
deployer = Deployer()
deployer.deploy()
# Can't do this :-(
# mock_installer.__init__.assert_called_once_with('foo', 'bar', 1)
# Try this instead
mock_installer.assert_called_once_with('foo', 'bar', 1)
所以,您收到的错误消息实际上是因为您没有正确检查模拟。您在这里必须了解的是,在您的装饰器中,您最终是在说,对 Installer
的调用将返回一个 Mock
对象。
因此,对于任何关于修补位置的 Installer()
调用,其 return 值将改为调用 Mock()
。
因此,您实际要检查的断言只是在 mock_installer
,而不是 mock_installer.__init__.
:
mock_installer.assert_called_once_with('foo', 'bar', 1)
这是对您的代码所做的修改:
class DeployerTest(unittest.TestCase):
@patch('Installer', autospec=True)
def testInstaller(self, mock_installer):
deployer = Deployer()
deployer.deploy()
mock_installer.assert_called_once_with('foo', 'bar', 1)
一些额外的信息来提供更多的解释,如果你现在正在测试是否在你的上下文管理器中调用了安装,你必须在这里意识到你实际上必须检查你的 __enter__
,所以结构将是这样的:
为了清晰起见,在您的测试方法中创建一个 mock_obj 并且:
mock_obj = mock_installer.return_value
现在,在您的上下文管理器中,您将需要查看对 __enter__()
的调用。如果您不知道这是为什么,请阅读上下文管理器。
因此,考虑到这一点,您只需按照以下方式执行检查:
mock_obj.__enter__().install.assert_called_once_with()
问题是 Installer(...)
没有直接调用 Installer.__init__
;相反,因为 Installer
是 type
的实例,并且定义了 type.__call__
,所以 Installer()
等同于
type.__call__(Installer, ...)
导致调用 Installer.__new__(Installer, ...)
,其 return 值 x
与原始参数一起传递给 Installer.__init__
。
所有这些都是说,由于您绑定到 Installer
的模拟对象不是 type
的实例,因此适用前面的 none。 Installer(...)
只是对模拟对象的调用,因此您可以直接检查:
mock_installer.assert_called_once_with('foo', 'bar', 1)
我正在使用 python 模拟来断言特定对象是使用正确的参数创建的。这是我的代码的样子:
class Installer:
def __init__(foo, bar, version):
# Init stuff
pass
def __enter__(self):
return self
def __exit__(self, type, value, tb):
# cleanup
pass
def install(self):
# Install stuff
pass
class Deployer:
def deploy(self):
with Installer('foo', 'bar', 1) as installer:
installer.install()
现在,我想断言 installer
是用正确的参数创建的。这是我目前的代码:
class DeployerTest(unittest.TestCase):
@patch('Installer', autospec=True)
def testInstaller(self, mock_installer):
deployer = Deployer()
deployer.deploy()
# Can't do this :-(
mock_installer.__init__.assert_called_once_with('foo', 'bar', 1)
这是我得到的错误:
File "test_deployment.py", line .., in testInstaller
mock_installer.__init__.assert_called_once_with('foo', 'bar', 1)
AttributeError: 'function' object has no attribute 'assert_called_once_with'
这是固定代码(称之为test.py
)。谢谢大家!
import unittest
from mock import patch
class Installer:
def __init__(self, foo, bar, version):
# Init stuff
pass
def __enter__(self):
return self
def __exit__(self, type, value, tb):
# cleanup
pass
def install(self):
# Install stuff
pass
class Deployer:
def deploy(self):
with Installer('foo', 'bar', 1) as installer:
installer.install()
class DeployerTest(unittest.TestCase):
@patch('tests.test.Installer', autospec=True)
def testInstaller(self, mock_installer):
deployer = Deployer()
deployer.deploy()
# Can't do this :-(
# mock_installer.__init__.assert_called_once_with('foo', 'bar', 1)
# Try this instead
mock_installer.assert_called_once_with('foo', 'bar', 1)
所以,您收到的错误消息实际上是因为您没有正确检查模拟。您在这里必须了解的是,在您的装饰器中,您最终是在说,对 Installer
的调用将返回一个 Mock
对象。
因此,对于任何关于修补位置的 Installer()
调用,其 return 值将改为调用 Mock()
。
因此,您实际要检查的断言只是在 mock_installer
,而不是 mock_installer.__init__.
:
mock_installer.assert_called_once_with('foo', 'bar', 1)
这是对您的代码所做的修改:
class DeployerTest(unittest.TestCase):
@patch('Installer', autospec=True)
def testInstaller(self, mock_installer):
deployer = Deployer()
deployer.deploy()
mock_installer.assert_called_once_with('foo', 'bar', 1)
一些额外的信息来提供更多的解释,如果你现在正在测试是否在你的上下文管理器中调用了安装,你必须在这里意识到你实际上必须检查你的 __enter__
,所以结构将是这样的:
为了清晰起见,在您的测试方法中创建一个 mock_obj 并且:
mock_obj = mock_installer.return_value
现在,在您的上下文管理器中,您将需要查看对 __enter__()
的调用。如果您不知道这是为什么,请阅读上下文管理器。
因此,考虑到这一点,您只需按照以下方式执行检查:
mock_obj.__enter__().install.assert_called_once_with()
问题是 Installer(...)
没有直接调用 Installer.__init__
;相反,因为 Installer
是 type
的实例,并且定义了 type.__call__
,所以 Installer()
等同于
type.__call__(Installer, ...)
导致调用 Installer.__new__(Installer, ...)
,其 return 值 x
与原始参数一起传递给 Installer.__init__
。
所有这些都是说,由于您绑定到 Installer
的模拟对象不是 type
的实例,因此适用前面的 none。 Installer(...)
只是对模拟对象的调用,因此您可以直接检查:
mock_installer.assert_called_once_with('foo', 'bar', 1)