好的,
我知道这在手册中有提及,可能side_effect与/和/有关return_value,但一个简单直接的例子对我帮助很大.
我有:
class ClassToPatch():
def __init__(self, *args):
_do_some_init_stuff()
def some_func():
_do_stuff()
class UUT():
def __init__(self, *args)
resource_1 = ClassToPatch()
resource_2 = ClassToPatch()
Run Code Online (Sandbox Code Playgroud)
现在,我想对这个UUT类进行单元测试,然后嘲笑ClassToPatch.知道UUT该类将实例化两个ClassToPatch对象,我希望Mock框架为每个实例化返回一个新的Mock对象,所以我可以稍后在每个实例上断言.
如何@patch在测试用例中使用装饰器实现此目的?即,如何修复以下代码示例?
class TestCase1(unittest.TestCase):
@patch('classToPatch.ClassToPatch',autospec=True)
def test_1(self,mock1,mock2):
_assert_stuff()
Run Code Online (Sandbox Code Playgroud) 我正在尝试测试一些使用os.walk的代码.我想创建一个临时的内存文件系统,我可以填充样本(空)文件和os.walk将返回的目录.这样可以省去模拟os.walk调用以模拟递归的复杂性.
具体来说,我要测试的代码是:
if recursive:
log.debug("Recursively searching for files under %s" % path)
for (dir_path, dirs, files) in os.walk(path):
log.debug("Found %d files in %s: %s" % (len(files), path, files))
for f in [os.path.join(dir_path, f) for f in files
if not re.search(exclude, f)]:
yield f
else:
log.debug("Non-recursively searching for files under %s" % path)
for (dir_path, dirs, files) in os.walk(path):
log.debug("Found %d files in %s: %s" % (len(files), path, files))
for f in [os.path.join(dir_path, f) for f in files
if not re.search(exclude, …Run Code Online (Sandbox Code Playgroud) 我正在开发一个涉及连接到远程服务器,等待响应,然后根据该响应执行操作的项目.我们捕获了几个不同的异常,并且根据捕获的异常而表现不同.例如:
def myMethod(address, timeout=20):
try:
response = requests.head(address, timeout=timeout)
except requests.exceptions.Timeout:
# do something special
except requests.exceptions.ConnectionError:
# do something special
except requests.exceptions.HTTPError:
# do something special
else:
if response.status_code != requests.codes.ok:
# do something special
return successfulConnection.SUCCESS
Run Code Online (Sandbox Code Playgroud)
为了测试这个,我们编写了如下测试
class TestMyMethod(unittest.TestCase):
def test_good_connection(self):
config = {
'head.return_value': type('MockResponse', (), {'status_code': requests.codes.ok}),
'codes.ok': requests.codes.ok
}
with mock.patch('path.to.my.package.requests', **config):
self.assertEqual(
mypackage.myMethod('some_address',
mypackage.successfulConnection.SUCCESS
)
def test_bad_connection(self):
config = {
'head.side_effect': requests.exceptions.ConnectionError,
'requests.exceptions.ConnectionError': requests.exceptions.ConnectionError
}
with mock.patch('path.to.my.package.requests', **config):
self.assertEqual(
mypackage.myMethod('some_address',
mypackage.successfulConnection.FAILURE
)
Run Code Online (Sandbox Code Playgroud)
如果我直接运行该函数,一切都按预期发生.我甚raise …
python exception-handling python-mock python-3.3 python-requests
我熟悉其他语言中的其他模拟库,例如Java中的Mockito,但Python的mock库让我的生活混乱.
我有以下课程,我想测试.
class MyClassUnderTest(object):
def submethod(self, *args):
do_dangerous_things()
def main_method(self):
self.submethod("Nothing.")
Run Code Online (Sandbox Code Playgroud)
在我的测试中,我想确保submethod在main_method执行时调用它,并使用正确的参数调用它.我不想submethod跑,因为它做危险的事情.
我完全不确定如何开始这个.Mock的文档非常难以理解,我不确定甚至可以模拟甚至如何模拟它.
如何submethod在main_method单独保留功能的同时模拟功能?
我需要MockMixin为我的测试创建一些.它应该包括调用外部源的所有内容的模拟.例如,每次我在管理面板中保存模型时,我都会调用一些远程URL.如果嘲笑并使用那样的话会很好:
class ExampleTestCase(MockedTestCase):
# tests
Run Code Online (Sandbox Code Playgroud)
因此,每次我在管理员中保存模型时,例如在功能测试中,应用此模拟而不是调用远程URL.
这有可能吗?我能够为1个特定测试做到这一点,这不是问题.但是有一些全局模拟更有用,因为我经常使用它.
我试图让mock.patch处理以下示例代码:
from mock import patch
from collections import defaultdict
with patch('collections.defaultdict'):
d = defaultdict()
print 'd:', d
Run Code Online (Sandbox Code Playgroud)
这输出如下:
d: defaultdict(None, {})
Run Code Online (Sandbox Code Playgroud)
这意味着defaultdict没有修补.
如果我用直接导入语句替换from/import语句,它可以工作:
from mock import patch
import collections
with patch('collections.defaultdict'):
d = collections.defaultdict()
print 'd:', d
Run Code Online (Sandbox Code Playgroud)
输出是:
d: <MagicMock name='defaultdict()' id='139953944084176'>
Run Code Online (Sandbox Code Playgroud)
有没有办法使用from/import修补呼叫?
谢谢
我应该如何自定义unittest.mock.mock_open来处理这段代码?
file: impexpdemo.py
def import_register(register_fn):
with open(register_fn) as f:
return [line for line in f]
Run Code Online (Sandbox Code Playgroud)
我第一次尝试尝试read_data.
class TestByteOrderMark1(unittest.TestCase):
REGISTER_FN = 'test_dummy_path'
TEST_TEXT = ['test text 1\n', 'test text 2\n']
def test_byte_order_mark_absent(self):
m = unittest.mock.mock_open(read_data=self.TEST_TEXT)
with unittest.mock.patch('builtins.open', m):
result = impexpdemo.import_register(self.REGISTER_FN)
self.assertEqual(result, self.TEST_TEXT)
Run Code Online (Sandbox Code Playgroud)
这失败了,大概是因为代码不使用read,readline或readlines.unittest.mock.mock_open 的文档说:"read_data是要返回的文件句柄的read(),readline()和readlines()方法的字符串.对这些方法的调用将从read_data中获取数据,直到它耗尽为止这些方法的模拟非常简单.如果你需要更多地控制你要测试代码的数据,你需要自己定制这个模拟.默认情况下,read_data是一个空字符串."
由于文件没有给出暗示上会需要什么样定制我试图return_value和side_effect.都没有奏效.
class TestByteOrderMark2(unittest.TestCase):
REGISTER_FN = 'test_dummy_path'
TEST_TEXT = ['test text 1\n', 'test text 2\n']
def test_byte_order_mark_absent(self):
m = unittest.mock.mock_open()
m().side_effect = self.TEST_TEXT
with unittest.mock.patch('builtins.open', m):
result = impexpdemo.import_register(self.REGISTER_FN) …Run Code Online (Sandbox Code Playgroud) 我有一个基类,它定义了一个类属性和一些依赖它的子类,例如
class Base(object):
assignment = dict(a=1, b=2, c=3)
Run Code Online (Sandbox Code Playgroud)
我想用不同的任务对这个类进行单元测试,例如空字典,单项等.当然,这非常简化,不是重构我的类或测试的问题.
我得到的(pytest)测试,最终,工作是
from .base import Base
def test_empty(self):
with mock.patch("base.Base.assignment") as a:
a.__get__ = mock.Mock(return_value={})
assert len(Base().assignment.values()) == 0
def test_single(self):
with mock.patch("base.Base.assignment") as a:
a.__get__ = mock.Mock(return_value={'a':1})
assert len(Base().assignment.values()) == 1
Run Code Online (Sandbox Code Playgroud)
这感觉相当复杂和hacky - 我甚至不完全理解为什么它工作(虽然我熟悉描述符).mock会自动将类属性转换为描述符吗?
一种感觉更符合逻辑的解决方案不起作用:
def test_single(self):
with mock.patch("base.Base") as a:
a.assignment = mock.PropertyMock(return_value={'a':1})
assert len(Base().assignment.values()) == 1
Run Code Online (Sandbox Code Playgroud)
要不就
def test_single(self):
with mock.patch("base.Base") as a:
a.assignment = {'a':1}
assert len(Base().assignment.values()) == 1
Run Code Online (Sandbox Code Playgroud)
我尝试过的其他变种也不起作用(测试中的作业保持不变).
模拟类属性的正确方法是什么?有没有比上面更好/更容易理解的方式?
我需要在测试中修补当前的日期时间.我正在使用这个解决方案:
def _utcnow():
return datetime.datetime.utcnow()
def utcnow():
"""A proxy which can be patched in tests.
"""
# another level of indirection, because some modules import utcnow
return _utcnow()
Run Code Online (Sandbox Code Playgroud)
然后在我的测试中我做了类似的事情:
with mock.patch('***.utils._utcnow', return_value=***):
...
Run Code Online (Sandbox Code Playgroud)
但今天我想到了一个想法,我可以通过修补__call__功能utcnow而不是额外的功能来简化实现_utcnow.
这对我不起作用:
from ***.utils import utcnow
with mock.patch.object(utcnow, '__call__', return_value=***):
...
Run Code Online (Sandbox Code Playgroud)
如何优雅地做到这一点?
我正在尝试为执行大量日期操作的django应用程序编写单元测试.我为我的测试安装了模拟猴子补丁django的timezone.now.
虽然我能够成功地嘲笑timezone.now时,它通常被称为(实际调用timezone.now()在我的代码,我不能嘲笑它为与一个创建的模型DateTimeField用default=timezone.now.
我有一个User包含以下内容的模型:
from django.utils import timezone
...
timestamp = models.DateTimeField(default=timezone.now)
modified = models.DateTimeField(default=timezone.now)
...
def save(self, *args, **kwargs):
if kwargs.pop('modified', True):
self.modified = timezone.now()
super(User, self).save(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)
我的单元测试看起来像这样:
from django.utils import timezone
def test_created(self):
dt = datetime(2010, 1, 1, tzinfo=timezone.utc)
with patch.object(timezone, 'now', return_value=dt):
user = User.objects.create(username='test')
self.assertEquals(user.modified, dt)
self.assertEquals(user.timestamp, dt)
Run Code Online (Sandbox Code Playgroud)
assertEquals(user.modified, dt)通过,但assertEquals(user.timestamp, dt)没有.
我怎么能模仿timezone.now,即使default=timezone.now在我的模型中也会创建模拟时间?
编辑
我知道我可以改变我的单元测试以通过timestamp …
python ×10
python-mock ×10
mocking ×7
unit-testing ×5
django ×2
iteration ×1
python-3.3 ×1
testing ×1
time ×1