我试图用unittest.mock模拟一个类。
我有以下包和模块结构:
类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类返回我分配给它的结果。但这并没有发生。
我也试过这样做。
@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()时,它被模拟替换。
这样做的正确方法是什么? (和最好的方式)
我是蟒蛇世界的佼佼者。我搜索并阅读了很多帖子,但所有显示的例子都非常简单(如sum()方法)。我已经用其他语言进行了测试,但从未在Python中进行过测试。
答案 0 :(得分:3)
如果你坚持使用patch
,你的最后一次尝试是正确的。
之前尝试不起作用的原因是因为修补程序是在导入后应用的,因此您不会修补您认为自己的对象。
我一直在使用补丁很长一段时间,这偶尔会让我感到伤心。所以我建议使用基于构造函数的简单依赖注入。
在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)
<强> N.B。补丁与依赖注入:
修补还会将测试耦合到程序的导入结构中。这使得安全重构更加难以改变模块的结构。当您需要在进行更改之前进行一些测试时,最好与遗留代码一起使用。