嘲笑一个类:赶上22

问题描述 投票:1回答:1

简要总结

MyClass.my_method打电话给instance = SomeLibrary()我想创建一个模拟器,所以instance是一个我可以控制的模拟对象。本着孤立测试的精神,我实际上并不想打电话给SomeLibrary

什么参数传递给@mock.patch()

我正在尝试模拟类构造函数,但我还没弄明白要传递给@ mock.patch()装饰器的内容。文档说必须完全点缀(pyftdi.ftdi.Ftdi),但where to patch文档说该参数必须与被测试代码知道它的名称相匹配(Ftdi)。我不知道如何满足两者。

为了使其具体,这是正在测试的文件:

from pyftdi.ftdi import Ftdi

class FtdiInterface(object):
    @classmethod
    def set_power(cls, url, on):
        ftdi = Ftdi()
        ftdi.open_from_url(url)
        # ... do other things with ftdi

......和测试文件

import unittest
from unittest import mock
from ftdi_interface import FtdiInterface
import pyftdi.ftdi

class TestFtdiInterface(unittest.TestCase):

    @mock.patch('pyftdi.ftdi.Ftdi')
    def testPowerOn(self, MockFtdi):
        url = 'some_string'
        ftdi_instance = mock.MagicMock()
        ftdi_instance.open_from_url = mock.MagicMock()
        MockFtdi.return_value = ftdi_instance

        FtdiInterface.set_power(url, True)
        ftdi_instance.open_from_url.assert_called_with(url)

我观察到的是,尽管我试图修补Ftdi(),但对ftdi_instance.open_from_url()的调用调用了库代码,而不是我的模拟对象。

我错过了什么?

python unit-testing mocking
1个回答
2
投票

Where to patch说:

基本原则是修改查找对象的位置,该位置不一定与定义对象的位置相同。

这意味着对于mockFtdi,你必须提供一个路径到你的代码中Ftdi实际实例化的地方。

要做到这一点,你需要用@mock.patch('pyftdi.ftdi.Ftdi')替换@mock.patch('ftdi_interface.Ftdi')

import unittest
from unittest import mock
from ftdi_interface import FtdiInterface

class TestFtdiInterface(unittest.TestCase):

    @mock.patch('ftdi_interface.Ftdi')
    def testPowerOn(self, MockFtdi):
        url = 'some_string'
        ftdi_instance = mock.MagicMock()
        ftdi_instance.open_from_url = mock.MagicMock()
        MockFtdi.return_value = ftdi_instance

        FtdiInterface.set_power(url, True)
        ftdi_instance.open_from_url.assert_called_with(url)

线import pyftdi.ftdi没有任何有用的测试,可以删除。

© www.soinside.com 2019 - 2024. All rights reserved.