Mocking 模拟对象
谈到单元测试时,你总是希望测试一段代码。但是你的代码可能依赖于 API 等第三方服务,你不想在本地测试期间调用它或者在你的 CI 环境中。这时候你应该使用模拟来模拟外部部分或你不想测试的部分。
Masonite 为某些依赖第三方服务的功能提供了一些模拟功能。
对于其他部分或你自己的代码,你可以使用 unittest.mock
标准模块提供的 Python 模拟功能。
Masonite 功能模拟
Masonite 测试用例有两个辅助方法 fake()
和 restore()
。
你可以通过执行 self.fake(feature) 来模拟 Masonite 功能,然后通过调用 self.restore(feature)
将其恢复为真实功能行为。当一个特性被模拟时,真正的行为不会被调用,而是运行一个快速简单的实现,通常提供检查和测试发生的事情的能力。
(目前)可以模拟的可用功能是:
模拟邮件
当模拟电子邮件时,它会阻止电子邮件被真正发送。通常,发送邮件与你实际测试的代码无关。最有可能的是,简单地断言 Masonite 被指示发送给定的可邮寄就足够了。
下面是一个如何模拟在测试中发送的电子邮件的示例:
def setUp(self):
super().setUp()
self.fake("mail")
def tearDown(self):
super().tearDown()
self.restore("mail")
def test_mock_mail(self):
welcome_email = self.application.make("mail").mailable(Welcome()).send()
(
welcome_email.seeEmailContains("Hello from Masonite!")
.seeEmailFrom("joe@masoniteproject.com")
.seeEmailCountEquals(1)
)
可用的断言有:
- seeEmailWasSent()
- seeEmailWasNotSent()
- seeEmailCountEquals(count)
- seeEmailTo(string)
- seeEmailFrom(string)
- seeEmailReplyTo(string)
- seeEmailBcc(string)
- seeEmailCc(string)
- seeEmailSubjectEquals(string)
- seeEmailSubjectContains(string)
- seeEmailSubjectDoesNotContain(string)
- seeEmailContains(string)
- seeEmailDoesNotContain(string)
- seeEmailPriority(string)
模拟通知
模拟通知时,通知不会被真正地发送。通常,发送通知与您实际测试的代码无关。最有可能的是,简单地断言 Masonite 被指示发送给定通知就足够了。
这是一个如何在测试中模拟发送通知的示例:
def setUp(self):
super().setUp()
self.fake("notifications")
def tearDown(self):
super().tearDown()
self.restore("notifications")
def test_mock_notification(self):
notification = self.application.make("notification")
notification.assertNothingSent()
notification.route("mail", "test@mail.com").send(WelcomeNotification())
notification.route("mail", "test@mail.com").send(WelcomeNotification())
notification.assertCount(2)
def test_mock_notification(self):
self.application.make("notification").route("mail", "test@mail.com").route(
"slack", "#general"
).send(OrderNotification(10))
self.application.make("notification").assertLast(
lambda user, notif: (
notif.assertSentVia("mail")
.assertEqual(notif.order_id, 10)
.assertEqual(
notif.to_slack(user).get_options().get("text"),
"Order 10 has been shipped !",
)
)
)
可用的断言有:
- assertNothingSent()
- assertCount(count)
- assertSentTo(notifiable, notification_class, callable_assert=None, count=None)
- assertLast(callable_assert)
- assertNotSentTo(notifiable, notification_class)
在通知实例上的可用断言:
- assertSentVia(*drivers)
- assertEqual(value, reference)
- assertNotEqual(value, reference)
- assertIn(value, container)
可用的助手函数有:
- resetCount()
- last()
基本的 Python 模拟
要模拟 Python 中的任何代码片段,您可以使用标准的 unittest.mock
模块。你可以在unittest documentation找到更多信息 。
下面是基本示例
from unittest.mock import patch
with patch("some.module") as SomeClass:
SomeClass.return_value.my_method.return_value = 0
self.assertEqual(SomeClass().my_method(), 0)
对于模拟外部 HTTP 请求,您可以使用 responses
模块。你可以在responses documentation找到更多信息。
import responses
@responses.activate
def test_mock_third_party_api(self):
responses.add(responses.POST, "api.github.com", body=b"Ok")
# 你的业务代码
self.assertTrue(responses.assert_call_count("api.github.com", 1))
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。