我需要模拟MyClassFactory
,它返回一个MyClass对象。该对象还具有方法getNum
,我也需要进行模拟。我不确定该如何执行此操作,因为工厂不再返回MyClass
,而是返回<MagicMock name='mock().create()'...>
。
import unittest
from mock import MagicMock, Mock, patch
class MyClass:
def getNum(self):
return 10
class MyClassFactory:
def create(self):
return MyClass()
class Runner:
def foo(self):
myClassFactory = MyClassFactory()
myClass = myClassFactory.create()
num = myClass.getNum()
if num == 10:
print("foo successful")
else:
print("foo fail, num={}".format(num))
class TestRoute(unittest.TestCase):
# Attempt at patching the methods
@patch("__main__.MyClassFactory", create=True, new=MagicMock())
@patch("__main__.MyClass", create=True, new=MagicMock())
@patch("__main__.MyClass.getNum", create=True, new=MagicMock(return_value=11))
def test_foo_fail(self):
runner = Runner()
runner.foo()
if __name__ == '__main__':
unittest.main()
实际输出:
foo fail, num=<MagicMock name='mock().create().getNum()' id='140554774258128'>
所需的输出:
foo fail, num=11
这不是我想要的<MagicMock name='mock().create().getNum()'...>
。我尝试将return_value=11
用于模拟方法,但是没有被调用。
TLDR:我有一个工厂需要模拟。它返回一个类。该类有一个方法,我还需要模拟不能做的return_value。基本上我想将mock().create().getNum()
变成11
。
答案 0 :(得分:1)
正在发生您的第一个补丁
@patch("__main__.MyClass", create=True, new=MagicMock())
用MagicMock()替换“ main .MyClass”的类实例。所以下一个补丁:
@patch("__main__.MyClass.getNum", create=True, new=MagicMock(return_value=11))
最终尝试调用MagicMock()对象的方法,而不是原始的 main .MyClass,这将导致您看到的输出。
You need to attach mocks as attributes and set up each child mock.与其在测试之前进行修补,不如在对foo的调用之前进行修补。
import unittest
from mock import MagicMock, Mock, patch
class MyClass:
def getNum(self):
return 10
class MyClassFactory:
def create(self):
return MyClass()
class Runner:
def foo(self):
myClassFactory = MyClassFactory()
myClass = myClassFactory.create()
print(myClassFactory)
print(myClass)
num = myClass.getNum()
if num == 10:
print("foo successful")
else:
print("foo fail, num={}".format(num))
class TestRoute(unittest.TestCase):
def test_foo_fail(self):
getNumMock = MagicMock(return_value = 20)
myClassMock = MagicMock()
myClassMock.getNum = getNumMock
createMock = MagicMock(return_value = myClassMock)
myClassFactoryMock = MagicMock()
createMock.attach_mock(getNumMock, "getNum")
myClassFactoryMock.attach_mock(createMock, "create")
with patch('__main__.MyClassFactory', create=True, return_value=myClassFactoryMock):
runner = Runner()
runner.foo()
if __name__ == '__main__':
unittest.main()