使用Django命令测试中的两个差异数据集对外部API调用进行补丁

时间:2019-07-16 13:56:24

标签: python django unit-testing mocking

我正在测试Django命令,该命令使用名为redminelib的外部API。

我的模拟类和修补程序在测试中运行良好,但是当我尝试使用两个不同的Mock实例在同一测试中对命令进行两次修补时,第二个命令调用使用第一个模拟类实例。

my_project/app/management/commands/redmine_command.py中的Django命令:

from redminelib import Redmine


class Command(BaseCommand):
    def handle(self, **options):
        key = 'project'
        redmine_api_instance = Redmine({'user': 'pass'})
        redmine_project = redmine_api_instance.project.get(key)
        print(redmine_project)

my_project/app/tests.py中:

import unittest
import json

from django.core.management import call_command
from django.test import TestCase

class MockProject:
    """A project mock class"""
    def __init__(self, time_entries: list):
        self.time_entries = time_entries


class MockRedmine(unittest.mock.MagicMock):
   """Class who will mock the redminelib API"""
    # Define directory which contains data files 
    json_data_dir = os.path.join(settings.BASE_DIR, "app/testdata/")

    def __init__(self, json_project_file, *args, **kwargs):
        super().__init__(json_project_file, *args, **kwargs)
        self.project = self.load(json_project_file)

    def load(self, json_file):
        json_filepath = os.path.join(MockRedmine.json_data_dir, json_file)
        with open(json_filepath, "r") as f:
            json_dict = json.load(f)
        project_dict = {key: MockProject(values) for key, values in json_dict.items()}
        return project_dict

# I test some case like this it works:
class TestCommand(TestCase):
    def test_invoice_creation_amount_and_update(self):
        with unittest.mock.patch("redminelib.Redmine") as redmine_mock_inst:
            mock_redmine = MockRedmine("api_case.json")
            redmine_mock_inst.return_value = mock_redmine
            call_command("my_command")

现在,我使用两个不同的数据集:api_case.jsonother_api_case.json

class TestCommadTwice(TestCase):
    def test_invoice_creation_amount_and_update(self):
        with unittest.mock.patch("redminelib.Redmine") as redmine_mock_inst1:
            mock_redmine1 = MockRedmine("api_case.json")
            redmine_mock_inst1.return_value = mock_redmine1
            call_command("redmine_command")

        with unittest.mock.patch("redminelib.Redmine") as redmine_mock_inst:
            mock_redmine = MockRedmine("other_api_case.json")
            redmine_mock_inst.return_value = mock_redmine
            call_command("redmine_command")

我希望redmine_command输出MockRedmine("api_case.json")然后是MockRedmine("other_api_case.json"),但是我有两次MockRedmine("api_case.json")

1 个答案:

答案 0 :(得分:0)

您需要使用unittest.mock.patch("app.management.commands.redmine_command.Redmine")

Docs

  

target应该是“ package.module.ClassName”形式的字符串。的   目标被导入,指定的对象被新的替换   对象,因此目标必须可从您所在的环境中导入   从调用patch()。装饰时导入目标   函数执行,而不是在装饰时执行。

另外,请查看https://docs.python.org/3/library/unittest.mock.html#id5Where to patch部分。