在类中使用的 Python 模拟 os.environ

Luc*_*cia 6 python unit-testing mocking python-unittest

我试图os.environ在课堂上进行模拟,但我就是做对了。这是我的结构:

#file.py
import os

class MyClass():
    connection_url = os.environ['DB']

#some code
Run Code Online (Sandbox Code Playgroud)

这是我的测试(无论如何都是最新的尝试):

#test.py
from unittest import TestCase
from unittest.mock import patch
from file import MyClass

class TestMyClass(TestCase):
    @patch.dict('file.os.environ', {'DB' : 'Dummy' })
    def setUp(self):
         self.class = MyClass()

#some testing
Run Code Online (Sandbox Code Playgroud)

这是悲惨地失败,引发 KeyError 'DB' ... 有人可以帮助我吗?我是 python 单元测试的新手。我研究了一些博客和 stackoverflow,尝试了一些解决方案,但无法解决问题。

提前致谢!

mgi*_*son 4

这里的问题是connection_url在创建类时(在导入时)设置的。如果你想模拟它,你可以在使用该属性之前修补类本身的属性:

class TestMyClass(TestCase):
    @patch.object(file.MyClass, 'connection_url', 'Dummy')
    def setUp(self):
        self.instance = MyClass()
Run Code Online (Sandbox Code Playgroud)

您仍然需要处理KeyError导入时的潜在问题 - 即,您需要确保您的测试运行程序在导入文件之前在环境中具有虚拟值,否则您必须将代码修改file.py为确保它不会引发KeyError. 这里有一些策略。如果未在环境中设置,您可以直接禁止KeyError出租:connection_url = default_value

class MyClass():
    connection_url = os.environ.get('DB', default_value)
Run Code Online (Sandbox Code Playgroud)

或者您可以将 connection_url 提取移至__init__

class MyClass():
    def __init__(self):
        connection_url = os.environ['DB']
Run Code Online (Sandbox Code Playgroud)

后一个代码还有一个额外的好处,您patch.dict应该开始工作。

请注意,如果您选择前两种方法中的任何一种,则实例将仅connection_url在该setUp方法期间进行修补 - 后续测试将不会进行修补。这很可能会成为一个阻碍,您需要在每个测试中创建一个新实例:

class TestMyClass(TestCase):
    @patch.object(file.MyClass, 'connection_url', 'Dummy')
    def test_first_thing(self):
        self.instance = MyClass()
        ...

    @patch.object(file.MyClass, 'connection_url', 'Dummy')
    def test_second_thing(self):
        self.instance = MyClass()
        ...
Run Code Online (Sandbox Code Playgroud)