允许在运行测试时“默认模拟”某些函数的实用程序。
automock的Python项目详细描述
用法
pip install automock
简介
关键思想是,我们为每个想要成为的函数定义一个"模拟工厂" 自动锁定的当调用时没有参数,工厂应该返回一个合适的 允许大多数测试通过的"默认"模拟。默认的模拟工厂是 只需从模拟库中调用magicmock即可。
注册要模拟的函数很简单:
importautomockautomock.register('services.users.client.get_user')
默认情况下,这将提供一个magicmock,相当于装饰所有的magicmock。 您的测试用例具有:
@mock.patch('services.users.client.get_user')
(有关更多情况,请参见下面的 自定义模拟工厂 )
要做到这一点,您只需要做两件事。
您需要确保包含 automock.register的模块 调用在测试运行之前被导入。为了达到这个目的,我们有一个 自动模拟注册导入 配置设置。它应该包含字符串路径 到包含注册调用的模块,例如:
AUTOMOCK_REGISTRATION_IMPORTS=('services.users.test_mocks','services.products.test_mocks','services.paypal.test_mocks',)
如果要在pytest下运行测试 那么您就不需要做任何其他事情了-automock注册了一个pytest插件 (在pytest中命名为 automock )确保您的测试用例都运行补丁。
如果您在另一个测试运行程序下运行,那么您的测试用例需要继承 从我们的一个助手类,例如:
fromautomockimportAutomockTestCase,AutomockTestCaseMixinclassTestWebViews(AutomockTestCase):...classTestSpecialViews(AutomockTestCaseMixin,MyCustomTestCase):...
这将确保在测试运行之前应用模拟修补程序,并停止 之后。
或者,您可以手动启动/停止修补:
fromunittestimportTestCaseimportautomockclassTestStuff(TestCase):# as a decorator@automock.activate()deftest_stuff(self):# automocks active...# as a context-managerdeftest_other_stuff(self):# automocks inactive...withautomock.activate():# automocks active...# automocks inactive
配置
设置要配置为prim通过一个python文件,比如 作为您现有的django settings.py 。要启动这个,有两个 控制配置的加载方式:
- 自动模拟应用程序配置 应该是python模块的导入路径,例如: 自动模拟应用程序配置=django.conf.settings
- 自动模拟配置名称空间 设置用于从env和 配置文件。默认为 自动模拟
以下配置键可用(并以前缀 automock默认情况下,请参见上面的 automock配置名称空间:
- <;namespace>;\u registration\u导入 到模块的导入路径列表 包含 automock.register 调用
修补和导入
关于您模拟的路径,需要注意的重要一点是:
这与直接使用mock.patch时有相同的注意事项。即 您必须修补导入路径
例如,如果您这样做:
# mypackage/mymodule.pyfromservices.product.clientimportget_product
当您修补时:
# won't work:patch('services.product.client.get_product')# works:patch('mypackage.mymodule.get_product')
别这样(看这个 博客文章 有关详细信息)。
如果我们希望在默认情况下模拟所有 特定函数的用法,因为我们只注册一条模拟路径。
相反,您需要在 使用要模拟的函数的代码库:
@mock.patch('services.users.client.get_user',return_value=MockUser(id=1))@mock.patch('services.products.client.get_product',return_value=MockProduct(id=1))@mock.patch('services.paypal.client.make_payment',return_value=PaypalResult('success'))deftest_some_web_view(self,*mocks)0
这将确保我们能够:
@mock.patch('services.users.client.get_user',return_value=MockUser(id=1))@mock.patch('services.products.client.get_product',return_value=MockProduct(id=1))@mock.patch('services.paypal.client.make_payment',return_value=PaypalResult('success'))deftest_some_web_view(self,*mocks)1
让它可靠地工作。
注意:
始终导入automock并用作automock.register以确保 只有一个注册表处于活动状态。
定制模拟工厂
很可能您需要做的不仅仅是提供一个简单的magicmock。例如 我们可能希望根据请求中的某些值自定义响应。
在mock.mock中,这是通过"副作用"实现的。所以我们可能想 像这样定义我们的模拟工厂:
@mock.patch('services.users.client.get_user',return_value=MockUser(id=1))@mock.patch('services.products.client.get_product',return_value=MockProduct(id=1))@mock.patch('services.paypal.client.make_payment',return_value=PaypalResult('success'))deftest_some_web_view(self,*mocks)2
注意,我们将自定义模拟工厂作为第二个参数传递给 寄存器
另外,我们可以使用decorator语法:
@mock.patch('services.users.client.get_user',return_value=MockUser(id=1))@mock.patch('services.products.client.get_product',return_value=MockProduct(id=1))@mock.patch('services.paypal.client.make_payment',return_value=PaypalResult('success'))deftest_some_web_view(self,*mocks)3
现在在我们的测试中,我们可以:
@mock.patch('services.users.client.get_user',return_value=MockUser(id=1))@mock.patch('services.products.client.get_product',return_value=MockProduct(id=1))@mock.patch('services.paypal.client.make_payment',return_value=PaypalResult('success'))deftest_some_web_view(self,*mocks)4
(当然,这是一个无用的测试,只是为了演示模拟)
好的。如果我们需要一个特定测试的自定义返回值呢?好吧,首先常规的mock.patch仍然有效,您可以将其应用于 您的测试用例。
automock还提供了一个swap mock帮助程序,它允许我们利用 我们的定制模拟工厂。
假设我们的工厂是这样的:
@mock.patch('services.users.client.get_user',return_value=MockUser(id=1))@mock.patch('services.products.client.get_product',return_value=MockProduct(id=1))@mock.patch('services.paypal.client.make_payment',return_value=PaypalResult('success'))deftest_some_web_view(self,*mocks)5
在我们的测试中,我们可以:
@mock.patch('services.users.client.get_user',return_value=MockUser(id=1))@mock.patch('services.products.client.get_product',return_value=MockProduct(id=1))@mock.patch('services.paypal.client.make_payment',return_value=PaypalResult('success'))deftest_some_web_view(self,*mocks)6
这里发生的是,swap-mock调用中的 *args,**kwargs 参数 被传递到 do_something_mock 以获取新的mock 然后应用于替代默认值。
我们还可以将其用作上下文管理器:
@mock.patch('services.users.client.get_user',return_value=MockUser(id=1))@mock.patch('services.products.client.get_product',return_value=MockProduct(id=1))@mock.patch('services.paypal.client.make_payment',return_value=PaypalResult('success'))deftest_some_web_view(self,*mocks)7
检查模拟调用
在测试中,通常需要检查是否调用了模拟函数,并且 如果直接使用mock.patch,这很容易 因为它将模拟对象返回给您。
automock提供 get mock帮助程序来实现相同的功能:
@mock.patch('services.users.client.get_user',return_value=MockUser(id=1))@mock.patch('services.products.client.get_product',return_value=MockProduct(id=1))@mock.patch('services.paypal.client.make_payment',return_value=PaypalResult('success'))deftest_some_web_view(self,*mocks)8
测试自动模拟功能
好吧,那么你已经模仿了你的api客户端或者其他什么。你怎么测试被模仿的 如果它们到处都被模仿的话,它们就会发挥作用?
首先,您不能继承那些测试中的automocktestcase。
但是,也许您还有一堆其他的自动模拟程序需要保持不变。
automock提供了一个k 助手:
@mock.patch('services.users.client.get_user',return_value=MockUser(id=1))@mock.patch('services.products.client.get_product',return_value=MockProduct(id=1))@mock.patch('services.paypal.client.make_payment',return_value=PaypalResult('success'))deftest_some_web_view(self,*mocks)9
(对于进行http调用的函数,我们推荐 响应 库)
在这里,我们取消了对客户机方法的模拟,以便能够正确地测试它 处理来自远程服务的404响应。