为什么我的 phyton 模拟只能使用特定的导入方式?

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

我有一个 utils 类,除了其他东西之外,它还有一个获取 id 的函数:

# utils.py
def get_id():
    return ...

另外,还有另一个类,比如说关于汽车的类,它使用这个函数:

# car.py
from utils import get_id

class Car:
    ...
    def setup(self):
        self.id = get_id()

我想运行一个应该提供特定ID的单元测试,这就是我嘲笑这个函数的原因:

# test_car.py
import unittest
from unittest.Mock import Mock
import utils

class TestCar(unittest.TestCase):
    ...

    def test_car_setup(self):
        utils.get_id = Mock(callable, return_value="my-testing-id")
        car = Car()
        car.setup()
        ...

但是这个模拟不起作用。我仍然得到原始函数的行为。 但是,我可以通过像这样调整汽车类别来使其工作:

# car.py
from . import utils

class Car:
    ...
    def setup(self):
        self.id = utils.get_id()

现在的问题是,为什么它可以工作,而以前的版本却不能? 我最初认为这可能是按引用调用/按值调用问题,但调试器显示现在无论我如何调整导入,utils 函数始终是同一个对象。

我知道这可能不是一个典型的问题,因为我的项目正在运行,但我无法理解导致它的Python的工作原理,如果有人能启发我,我将不胜感激。

提前致谢!

python python-3.x unit-testing testing mocking
1个回答
0
投票

改变
test_car.py

对您的文件

test_car.py
进行一些更改就足够了,而
car.py
utils.py
保持不变;文件
car.py
与原始
from utils import get_id
如下所示:

# car.py
from utils import get_id

class Car:
    ...
    def setup(self):
        self.id = get_id()

下面我向您展示文件

test_car.py

#test_car.py
import unittest
from unittest.mock import Mock
#import utils                      # <----- this import is now useless
from car import Car                # <----- add this import
import car as module_car           # <----- add this import (added name module_car
                                   #        to avoid name collision)

class TestCar(unittest.TestCase):

    def test_car_setup(self):
        # I have commented your instruction
        #utils.get_id = Mock(callable, return_value="my-testing-id")
        
        # USE THIS INSTRUCTION 
        module_car.get_id = Mock(callable, return_value="my-testing-id")
        car = Car()
        car.setup()

if __name__ == '__main__':
    unittest.main()

说明

所需的更改如下:

utils.get_id = Mock(callable, return_value="my-testing-id") ---> module_car.get_id = Mock(callable, return_value="my-testing-id")
  • 指令

    module_car.get_id = Mock(...)
    替换模块内部使用的名称
    get_id
    所指向的对象
    car.py

  • 您的指令 (

    utils.get_id = Mock(...)
    ) 替换了文件
    get_id
    中名称
    utils.py
    指向的对象,但方法
    setup()
    使用的对象是由
    get_id
    内部定义的名称
    car.py
    指向的。

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