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()
を呼び出すと、その戻り値は代わりに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)
_
コンテキストマネージャー内でinstallが呼び出されたかどうかを今すぐテストしている場合、ここで実際に___enter__
_の内部をチェックする必要があることを理解する必要があるため、構造は次のようになります。 :
わかりやすくするために、テストメソッドでmock_objを作成します。
_mock_obj = mock_installer.return_value
_
これで、コンテキストマネージャー内で、__enter__()
の呼び出しの内部を調べるためにneedになります。これがなぜなのかわからない場合は、コンテキストマネージャーを読んでください。
したがって、それを念頭に置いて、次のようにチェックを実行するだけです。
_mock_obj.__enter__().install.assert_called_once_with()
_
問題は、Installer(...)
が_Installer.__init__
_を直接呼び出さないことです。むしろ、Installer
はtype
のインスタンスであり、_type.__call__
_が定義されているため、Installer()
は次と同等になります。
_type.__call__(Installer, ...)
_
その結果、Installer.__new__(Installer, ...)
が呼び出され、その戻り値x
が元の引数とともに_Installer.__init__
_に渡されます。
つまり、Installer
にバインドするモックオブジェクトはtype
のインスタンスではないため、上記のいずれも当てはまりません。 Installer(...)
は単にモックオブジェクトの呼び出しであるため、次のことを直接確認します。
_mock_installer.assert_called_once_with('foo', 'bar', 1)
_