Python的模拟框架
项目描述
Func是一个受JMock影响的Python模拟框架。Func通过允许使用模拟对象代替“真实”对象,帮助测试模块的隔离。Func采用2条款BSD许可证。
安装
$ pip install funk
示例
假设我们有一个文件存储服务的API。我们想列出所有文件的名字,但是API限制了它一次返回的名字数量。因此,我们需要编写一些代码,不断向API请求数据,直到所有名字都被检索到。
def fetch_names(file_storage):
has_more = True
token = None
names = []
while has_more:
response = file_storage.names(token=token)
names += response.names
token = response.next_token
has_more = token is not None
return names
import funk
@funk.with_mocks
def test_request_for_names_until_all_names_are_fetched(mocks):
file_storage = mocks.mock(FileStorage)
mocks.allows(file_storage).names(token=None).returns(mocks.data(
next_token="<token 1>",
names=["a", "b"],
))
mocks.allows(file_storage).names(token="<token 1>").returns(mocks.data(
next_token="<token 2>",
names=["c", "d"],
))
mocks.allows(file_storage).names(token="<token 2>").returns(mocks.data(
next_token=None,
names=["e"],
))
assert fetch_names(file_storage) == ["a", "b", "c", "d", "e"]
通过使用模拟对象而不是FileStorage的真实实例,我们可以在没有运行文件存储系统实例的情况下运行我们的测试。我们还避免了依赖FileStorage的实现,使我们的测试更加集中,更少脆弱。
如果您使用pytest,使用Func的最简单方法是将它作为一个fixture使用
import funk
import pytest
@pytest.yield_fixture
def mocks():
mocks = funk.Mocks()
yield mocks
mocks.verify()
def test_request_for_names_until_all_names_are_fetched(mocks):
file_storage = mocks.mock(FileStorage)
...
用法
创建模拟上下文
创建一个Mocks实例以允许创建模拟对象。调用Mocks.verify()来断言所有预期都已满足。
import funk
def test_case():
mocks = funk.Mocks()
...
mocks.verify()
使用装饰器funk.with_mocks将一个mocks参数注入到一个函数中。函数结束时将自动调用verify()。
import funk
@funk.with_mocks
def test_case(mocks):
...
如果您使用pytest,使用fixture是使用Func的最简单方法
import funk
import pytest
@pytest.yield_fixture
def mocks():
mocks = funk.Mocks()
yield mocks
mocks.verify()
def test_case(mocks):
...
创建模拟对象
调用Mocks.mock()来创建模拟对象。
file_storage = mocks.mock()
如果传递了base参数,则只能模拟该类型的方法
file_storage = mocks.mock(FileStorage)
这可以确保仅模拟现有方法,但如果使用 __getattr__ 等动态生成方法时应该避免。
将 name 参数设置为在模拟断言失败消息中应使用的名称。
file_storage = mocks.mock(name="file_storage")
设置期望
要设置期望,请使用 funk.allows() 或 funk.expects()。为了方便,这些函数也可以在 Mocks 上使用。funk.allows() 允许方法被调用任意次数,包括零次。funk.expects() 将确保方法被恰好调用一次。例如
allows(file_storage).names
这允许方法 file_storage.names 可以用任何参数调用任意次数。如果只想允许调用具有特定参数的方法,可以像调用方法一样调用 .names。
allows(file_storage).names(token="<token 1>")
这将只允许带有匹配的 token 关键字参数的调用,不允许其他参数。
您还可以使用来自 Precisely 的匹配器来匹配参数。
from precisely import instance_of
allows(file_storage).names(token=instance_of(str))
如果在同一方法上设置了多个期望,则使用第一个匹配的期望。如果您需要强制按特定顺序调用方法,请使用序列。
操作
默认情况下,模拟方法返回 None。使用 returns() 返回不同的值。
allows(file_storage).names().returns([])
使用 raises() 抛出异常。
allows(file_storage).names().raises(Exception("Could not connect"))
序列
可以使用 Mocks.sequence 创建序列对象。然后可以在设置期望时使用 in_sequence(sequence) 定义对象的序列。例如
file_storage = mocks.mock(FileStorage)
file_ordering = mocks.sequence()
expects(file_storage).save(NAME_1, CONTENTS_1).in_sequence(file_ordering)
expects(file_storage).save(NAME_2, CONTENTS_2).in_sequence(file_ordering)
项目详情
下载文件
下载您平台的文件。如果您不确定选择哪个,请了解有关 安装包 的更多信息。
源分发
构建分发
Funk-0.5.0.tar.gz 的散列
算法 | 散列摘要 | |
---|---|---|
SHA256 | 59e954b744dacc28785bd81abe11dd9957dc5a4774db949b573f2c3861cfe84c |
|
MD5 | 869335712359c1a33bc270604aabcf62 |
|
BLAKE2b-256 | 8d25fbf23cd90e3fac6068d6dd60110108f174f9a0d9a142aa6d86d8e5a1be74 |
Funk-0.5.0-py2.py3-none-any.whl 的散列
算法 | 散列摘要 | |
---|---|---|
SHA256 | 62eeaa238b668171756e75b5bda8a02cea86e8d55c55f4d0417f52246d6f9101 |
|
MD5 | b8c94932c6fc7eaf4f27cd43fa3df6c2 |
|
BLAKE2b-256 | b160e8f3dbe06a3c858a131c6ee3ec11b7a10c313b0c2a64519d889aee8fe647 |