我的代码使用pytest相当多.示例代码结构如下所示.整个代码库是python-2.7
core/__init__.py
core/utils.py
#feature
core/feature/__init__.py
core/feature/service.py
#tests
core/feature/tests/__init__.py
core/feature/tests/test1.py
core/feature/tests/test2.py
core/feature/tests/test3.py
core/feature/tests/test4.py
core/feature/tests/test10.py
Run Code Online (Sandbox Code Playgroud)
本service.py看起来是这样的:
from modules import stuff
from core.utils import Utility
class FeatureManager:
# lots of other methods
def execute(self, *args, **kwargs):
self._execute_step1(*args, **kwargs)
# some more code
self._execute_step2(*args, **kwargs)
utility = Utility()
utility.doThings(args[0], kwargs['variable'])
Run Code Online (Sandbox Code Playgroud)
所有测试feature/tests/*最终都使用了core.feature.service.FeatureManager.execute功能.但是utility.doThings(),在运行测试时,我没有必要运行.我需要它在生产应用程序运行时发生,但我不希望它在测试运行时发生.
我可以做我这样的事 core/feature/tests/test1.py
from mock import patch
class Test1:
def test_1():
with patch('core.feature.service.Utility') as MockedUtils:
exectute_test_case_1()
Run Code Online (Sandbox Code Playgroud)
这会奏效.但是我Utility刚刚添加到代码库中,我有超过300个测试用例.我不想进入每个测试用例并写下这个with语句.
我可以写一个conftest.py设置一个os级环境变量,根据该环境变量core.feature.service.FeatureManager.execute …
在为我的应用程序编写单元测试时,我一直在使用@mock.patch和@patch.object装饰器。但是现在,对于使用装饰器时的某些单元测试,我收到错误“ TypeError: staticmethod object is not an iterator ”。
但是使用相同的代码,如果我使用mock.patch.objector mock.patch.object,一切正常。
例如,在我的测试类中,我有这个方法:
@staticmethod
def my_mock():
...do something
Run Code Online (Sandbox Code Playgroud)
当我尝试以下单元测试时
@mock.patch('mypackage.mymodule.my_method', side_effect=my_mock)
def test_something(self, my_method_mocked):
...test something
Run Code Online (Sandbox Code Playgroud)
我收到了“ TypeError: staticmethod object is not an iterator ”之前所述的错误消息。
但是当我尝试这种方式时
def test_something(self):
with patch.object(mymodule, "my_method") as mocked_method:
mocked_method.side_effect = self.my_mock
...test something
Run Code Online (Sandbox Code Playgroud)
然后一切正常。
我已经阅读了有关模拟和单元测试的 Python 文档,但找不到对此行为的任何解释。
使用装饰器模式和使用模式有什么区别?我在哪里可以找到更多关于这方面的信息?
为了更清楚,这是我的代码结构:
class TestClass(unittest.TestCase):
@staticmethod
def my_mock():
...mock
return service
# doesn't work
@mock.patch('mypackage.mymodule.my_method', side_effect=my_mock)
def test_something(self, my_method_mocked): …Run Code Online (Sandbox Code Playgroud) 我编写了send_formatted_email格式化电子邮件主题和消息的send_email函数,然后在单独的模块中调用该函数。
现在我要测试send_formatted_email的调用send_email与预期的参数。为此,我试图模拟send_emailusing patch,但它并没有被模拟。
测试文件
@patch('app.util.send_email')
def test_send_formatted_email(self, mock_send_email):
mock_send_email.return_value = True
response = send_formatted_email(self.comment, to_email)
mock_send_email.call_args_list
....
Run Code Online (Sandbox Code Playgroud)
视图.py
def send_formatted_email(comment, to_email):
...
message = comment.comment
subject = 'Comment posted'
from_email = comment.user.email
...
return send_email(subject, message, to_email, from_email)
Run Code Online (Sandbox Code Playgroud)
实用程序
def send_email(subject, message, to, from):
return requests.post(
...
)
Run Code Online (Sandbox Code Playgroud)
我什至尝试过,app.util.send_email = MagicMock(return_value=True)但这也不起作用。知道我做错了什么吗?
我想要什么:
确保Foo在with语句中创建的所有实例都foo通过wraps=Foo.foo. 我想要这个的原因是我可以跟踪创建的所有实例call_count的方法。现在我这么说似乎有点不可能......fooFoo
>>> from mock import patch
...
... class Foo(object):
...
... def foo(self):
... return "foo"
...
... with patch("__main__.Foo.foo", wraps=Foo.foo) as m:
... foo = Foo()
... print(foo.foo())
Traceback (most recent call last):
File "a.py", line 12, in <module>
print(foo.foo())
File "/disk/software/lib/python27/mock/mock.py", line 1062, in __call__
return _mock_self._mock_call(*args, **kwargs)
File "/disk/software/lib/python27/mock/mock.py", line 1132, in _mock_call
return self._mock_wraps(*args, **kwargs)
TypeError: unbound method foo() must be …Run Code Online (Sandbox Code Playgroud) 假设,我有一个代码片段
foo = SomeClass()
bar = foo[1:999].execute()Run Code Online (Sandbox Code Playgroud)
为了测试这一点,我尝试了一些
foo_mock = Mock()
foo_mock[1:999].execute()Run Code Online (Sandbox Code Playgroud)
不幸的是,这引发了一个例外,
类型错误:“模拟”对象不可下标
那么,如何创建可下标的 Mock对象?
我想创建一个mock.Mock()对象,然后添加一个称为session实例方法的方法,该方法传递self对模拟对象的引用,允许该方法向模拟对象添加状态。这是可能的(无需手动使用types.MethodType,例如,使用模拟的内置 API),还是我应该找到解决方法?
请注意,我发现了这个问题,它是针对 Ruby 的,似乎涵盖了类似的内容,如果不是同一件事的话。不幸的是,我根本不了解 Ruby。
有没有一种简单的方法来在Python中模拟松散定义的dict对象?例如,如何在给定dict的情况下轻松表达input,我想检查其中的每个值是否符合特定的元定义,如最小值和最大值,长度和类型?
能够这样做可能很方便,例如,在编写测试时.
在mock(Python版本3.3+中的unittest.mock)中,可以指定值可以是ANY值,例如
>>> mock = Mock(return_value=None)
>>> mock('foo', bar=object())
>>> mock.assert_called_once_with('foo', bar=ANY)
Run Code Online (Sandbox Code Playgroud)
但是,如果bar上面应该是类似dict的对象,就像
>>> {'baz': <an integer between -3 and 14>, 'qux': <'yes' or 'no'>}
Run Code Online (Sandbox Code Playgroud) 我最近开始在 python 中使用模拟框架。似乎如果我修补一个函数,则不会调用实际代码-这意味着未实现此实际函数所做的数据库更改等。我一直试图通过事先调用函数并存储返回值并将其作为 arg 传递到 patch() 来绕过它,但是有没有更好的方法来做到这一点?理想情况下,我想要一个可以用作 a 的代码,silent observer我可以简单地询问它是否observed调用了某个函数,调用了多少次,以及使用了哪些参数
return_val = funct()
# C: Now call me again and assert that these intensive computation functions are not called but taken from cache
with patch('funct', return_value=return_val) as mock_task:
me_response = self.client.get(me_url, format='json') #should fetch from cache
assert not mock_task.called
Run Code Online (Sandbox Code Playgroud) 我正在尝试为我正在编写的应用程序设置一个测试装置,其中我的一个类被模拟替换。我很高兴将模拟类的大部分属性保留为默认MagicMock实例(我只对它们的用法做出断言感兴趣),但该类还有一个属性,我想为其提供特定的返回值.
作为参考,这是我试图修补的类的大纲:
class CommunicationService(object):
def __init__(self):
self.__received_response = Subject()
@property
def received_response(self):
return self.__received_response
def establish_communication(self, hostname: str, port: int) -> None:
pass
def send_request(self, request: str) -> None:
pass
Run Code Online (Sandbox Code Playgroud)
我遇到的困难是,当我修补时CommunicationService,我还尝试为将返回特定值PropertyMock的received_response属性设置 a 。然而,当我在我的生产代码中实例化这个类时,我发现调用CommunicationService.received_response返回的是默认MagicMock实例而不是我希望它们返回的特定值。
在测试设置期间,我执行以下操作:
context.mock_comms_exit_stack = ExitStack()
context.mock_comms = context.mock_comms_exit_stack.enter_context(
patch('testcube.comms.CommunicationService', spec=True))
# Make 'received_response' observers subscribe to a mock subject.
context.mock_received_response_subject = Subject()
type(context.mock_comms).received_response = PropertyMock(return_value=context.mock_received_response_subject)
# Reload TestCube module to make it import the …Run Code Online (Sandbox Code Playgroud) 今天我意识到unittest.mock.patch如何导入函数很重要。取决于mock.patch呼叫工作或被忽略的使用方式。在 Python 中,我们通常导入一个函数:
import os或这样的导入语句from ... import ...像这样的声明from os import systemmock.patch如果我使用A就像一个魅力import os,但如果我修补了它,它会被忽略from os import system。
示例 1:使用导入
import os
from unittest import mock
def echo():
os.system('echo "Hello"')
with mock.patch('os.system') as mocked:
print(mocked)
mocked.side_effect = Exception('Patch works!')
echo()
Run Code Online (Sandbox Code Playgroud)
示例 1 的输出
<MagicMock name='system' id='140037358656760'>
Traceback (most recent call last):
File "/.../config/scratches/scratch_7.py", line 12, in <module>
echo()
File "/.../config/scratches/scratch_7.py", line 6, in echo
os.system('echo "Hello"')
File "/.../python3.5/unittest/mock.py", …Run Code Online (Sandbox Code Playgroud) python-mock ×10
python ×9
python-2.7 ×3
unit-testing ×3
mocking ×2
pytest ×2
python-3.x ×2
django ×1
patch ×1
tdd ×1