我正在使用Python模拟模块进行测试。我想用模拟替换活动对象,并自动将对模拟对象的所有调用转发到原始对象。我认为这在标准测试术语中被称为“间谍”。目前我正在测试中:
# Insert a mock replacement
orig_active_attr = server.active_attr
server.active_attr = mock.Mock()
# Set up side effects to 'proxy' to the original object
server.active_attr.meth1.side_effect = orig_active_attr.meth1
server.active_attr.meth2.side_effect = orig_active_attr.meth2
# Call the method being tested
server.method_being_tested()
# Assert stuff on the mock.
server.active_attr.meth2.assert_called_once()
如果模拟器上的所有方法调用都可以在没有样板的情况下自动转发到活动对象,那将是很好的。
答案 0 :(得分:23)
我似乎偶然发现了解决方案:
import mock
class A(object):
def meth(self, a):
return a
a = A()
ma = mock.Mock(wraps=a)
似乎可以正常使用函数,方法和属性,但不适用于类或实例属性。
答案 1 :(得分:5)
您可以按照Spying on instance methods with Python's mock module中的建议使用patch.object(wraps=obj_instance)
。
例如:
from mock import patch
class Foo(object):
def bar(self, x, y):
return x + y + 1
def test_bar():
foo = Foo()
with patch.object(foo, 'bar', wraps=foo.bar) as wrapped_foo:
foo.bar(1, 2)
wrapped_foo.assert_called_with(1, 2)
答案 2 :(得分:1)
您可以使用一个简单的函数来遍历所有方法并配置模拟
import inspect
def spy_mock(instance):
members = inspect.getmembers(instance, inspect.ismethod)
attrs = {'%s.side_effect' % k:v for k,v in members}
return mock.Mock(**attrs)
server.active_attr = spy_mock(server.active_attr)
答案 3 :(得分:0)
这是仅模拟datetime.date.today()
并将剩余的datetime
调用转发到datetime
模块的方法:
from unittest import mock, TestCase
import foo_module
class FooTest(TestCase):
@mock.patch(f'{foo_module.__name__}.datetime', wraps=datetime)
def test_something(self, mock_datetime):
# mock only datetime.date.today()
mock_datetime.date.today.return_value = datetime.date(2019, 3, 15)
# other calls to datetime functions will be forwarded to original datetime
foo_module
导入datetime
并使用datetime
以外的许多其他date.today
函数。