我正在尝试使用 unittest.mock 模拟一个类。
我有以下包和模块结构:
- 服务
- service_one.py
- 存储库
- repository_mongodb.py
- 测试
- 服务
- test_service_one.py
- 服务
类repository_mongodb.py在类service_one.py中使用(通过导入该类)。
这是文件的代码。
文件repository_mongodb.py
class RepositoryMongoDB:
def __init__(self):
self.library = []
def save(self, thing):
self.library.append(thing)
return True
文件service_one.py
from repository.RepositoryBookList import RepositoryBookList
class ServiceRodri:
def __init__(self):
self.repository = RepositoryMongoDB()
def save_service(self, thing):
# Do validation or something else
return self.repository.save(thing)
现在我想尝试模拟 ServiceRodri 类,这就是我所做的。
import unittest
from unittest.mock import patch
from service.service_one import ServiceOne
class ServiceOneTest(unittest.TestCase):
def setUp(self):
self.service_one = ServiceOne()
@patch('service.service_one.RepositoryMongoBD')
def test_get_one_book_if_exists_decorator(self, mock_repo):
mock_repo.save.return_value = "call mock"
result = self.serviceRodri.save_service("")
self.assertEquals("call mock", result)
我希望当我调用 RepositoryMongoBD 类的“save”方法时返回分配给它的结果。但这并没有发生。
我也尝试过这样做。
@patch('repository.repository_mongodb.RepositoryMongoDB')
def test_get_one_book_if_exists_decorator(self, mock_repo):
mock_repo.save.return_value = "call mock"
result = self.serviceRodri.save_service("")
self.assertEquals("call mock", result)
但它也不起作用。
但是如果我尝试以这种方式模拟函数save()。
@patch('service.service_one.RepositoryMongoDB.save')
def test_get_one_book_if_exists_decorator_2(self, mock_repo):
mock_repo.return_value = "call mock"
result = self.serviceRodri.save_service("")
self.assertEquals("call mock", result)
工作正常!!!我明白它的作用是当在 service_one 模块中找到调用 save() 时,它会被模拟替换。
正确的做法是什么? (也是最好的方法)
我是Python世界的初学者。我搜索并阅读了很多帖子,但是显示的所有示例都非常简单(例如 sum() 方法)。我已经用其他语言进行了测试,但从未在 Python 中进行过测试。
最佳答案
如果您坚持使用patch
,那么您的最终尝试是正确的方法。
之前的尝试不起作用的原因是因为补丁是在导入后应用的,所以您没有修补您认为是的对象。
我已经使用 patch 很长时间了,但这个问题仍然偶尔会困扰我。因此我建议使用基于简单构造函数的依赖注入(inject)。
在 service_one 中
class ServiceOne:
def __init__(self, respository):
self.repository
使用 service_rodri = ServiceRodri(RepositoryMongoDB())
初始化它,可能在 __init__
文件或其他文件中。然后在您的测试中,您可以在您的设置中创建此模拟。
class ServiceOneTest(unittest.TestCase):
def setUp(self):
self.repository = MagicMock()
self.service_one = ServiceOne(self.repository)
注意修补与依赖注入(inject):
修补还将测试与程序的导入结构结合起来。这使得严格改变模块结构的安全重构变得更加困难。当您需要在进行更改之前进行一些测试时,它最好与遗留代码一起使用。
关于python - 使用 unittest 在 Python 中模拟类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50025322/