使用unittest

时间:2018-04-25 14:50:41

标签: python python-3.x python-unittest

我试图用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类返回我分配给它的结果。但这并没有发生。

我也试过这样做。

    @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中进行过测试。

1 个答案:

答案 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。补丁与依赖注入:

修补还会将测试耦合到程序的导入结构中。这使得安全重构更加难以改变模块的结构。当您需要在进行更改之前进行一些测试时,最好与遗留代码一起使用。