jpa*_*kal 41 python unit-testing mocking
Rubyist在这里编写Python.我有一些看起来像这样的代码:
result = database.Query('complicated sql with an id: %s' % id)
Run Code Online (Sandbox Code Playgroud)
database.Query被模拟了,我想测试ID是否被正确注入而不将整个SQL语句硬编码到我的测试中.在Ruby/RR中,我会这样做:
mock(database).query(/#{id}/)
Run Code Online (Sandbox Code Playgroud)
但是我无法在unittest.mock中看到像这样设置'选择性模拟'的方法,至少没有一些毛茸茸的side_effect逻辑.所以我尝试在断言中使用正则表达式:
with patch(database) as MockDatabase:
instance = MockDatabase.return_value
...
instance.Query.assert_called_once_with(re.compile("%s" % id))
Run Code Online (Sandbox Code Playgroud)
但这也不起作用.这种方法确实有效,但它很难看:
with patch(database) as MockDatabase:
instance = MockDatabase.return_value
...
self.assertIn(id, instance.Query.call_args[0][0])
Run Code Online (Sandbox Code Playgroud)
好主意?
fal*_*tru 61
import mock
class AnyStringWith(str):
def __eq__(self, other):
return self in other
...
result = database.Query('complicated sql with an id: %s' % id)
database.Query.assert_called_once_with(AnyStringWith(id))
...
Run Code Online (Sandbox Code Playgroud)
编辑:抢先需要匹配的字符串
def arg_should_contain(x):
def wrapper(arg):
assert str(x) in arg, "'%s' does not contain '%s'" % (arg, x)
return wrapper
...
database.Query = arg_should_contain(id)
result = database.Query('complicated sql with an id: %s' % id)
Run Code Online (Sandbox Code Playgroud)
小智 17
你可以使用unittest.mock.ANY:)
from unittest.mock import Mock, ANY
def foo(some_string):
print(some_string)
foo = Mock()
foo("bla")
foo.assert_called_with(ANY)
Run Code Online (Sandbox Code Playgroud)
如此处所述 - https://docs.python.org/3/library/unittest.mock.html#any
您可以使用match_equalityPyHamcrest库来包装matches_regexp同一库中的匹配器:
from hamcrest.library.integration import match_equality
with patch(database) as MockDatabase:
instance = MockDatabase.return_value
...
expected_arg = matches_regexp(id)
instance.Query.assert_called_once_with(match_equality(expected_arg))
Run Code Online (Sandbox Code Playgroud)
Python 的文档中也提到了这个方法unittest.mock:
从版本 1.5 开始,Python 测试库 PyHamcrest 提供了类似的功能,在这里可能有用,其形式是等式匹配器 (hamcrest.library.integration.match_equality)。
如果您不想使用 PyHamcrest,上面链接的文档还展示了如何通过定义带有__eq__方法的类来编写自定义匹配器(如falsetru答案中所建议的):
class Matcher:
def __init__(self, compare, expected):
self.compare = compare
self.expected = expected
def __eq__(self, actual):
return self.compare(self.expected, actual)
match_foo = Matcher(compare, Foo(1, 2))
mock.assert_called_with(match_foo)
Run Code Online (Sandbox Code Playgroud)
self.compare您可以用您自己的正则表达式匹配替换对此处的调用,False如果没有找到则返回,或者引发AssertionError带有您选择的描述性错误消息的 。
| 归档时间: |
|
| 查看次数: |
11853 次 |
| 最近记录: |