You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python单元测试问题:if语句内导入的模块未定义

解决unittest.mock中NameError: name 'other_module' is not defined的问题

我来帮你梳理下问题根源和解决办法——你遇到的这个坑其实是Python模块加载机制导致的,很常见但容易踩:

为什么会报错?

当你在测试文件里执行import my_code的瞬间,my_code.py的所有顶层代码会被一次性执行完毕。此时some_module.DO_IMPORT的原始值是False,所以那个条件导入import other_module根本没跑起来。

后来你用@patch把some_module.DO_IMPORT改成True,但模块已经加载完成了,Python不会再回头重新执行那些顶层代码,所以my_func里访问other_module时,这个模块根本没被导入,自然就报NameError了。

另外还要提一下你代码里的几个小bug,不然就算解决了导入问题也会报错:

  • Python的布尔值是大写的True/False,不是小写的true/false
  • 测试类要继承unittest.TestCase才能用self.assertTrue这些断言
  • my_func定义时带了self参数,调用时得传个对象进去(比如测试类的self)
  • 你测试方法名写成了def_test_my_func,少了空格,应该是def test_my_func(self, *_):

几种可行的解决方案

方案1:在patch生效后重新加载模块

我们可以先把已经加载的my_code从sys.modules里删掉,然后重新导入,这样模块会在DO_IMPORT=True的上下文里重新执行所有顶层代码,包括那个条件导入:

修改后的测试代码:

from unittest.mock import patch, Mock
import sys
import importlib
import unittest
import my_code

class TestMyCode(unittest.TestCase):
    @patch('my_code.some_module', DO_IMPORT=True)
    def test_my_func(self, *_):
        # 移除已加载的模块
        del sys.modules['my_code']
        # 重新导入,此时DO_IMPORT是True,会执行import other_module
        import my_code
        # 调用函数并断言
        ret = my_code.my_func(self)
        self.assertTrue(ret)

方案2:把导入移到函数内部(修改原代码)

如果允许改动my_code.py,可以把import other_module放到my_func里面,这样每次调用函数时都会检查条件并执行导入,彻底避开模块加载时机的问题:

修改后的my_code.py:

import some_module

def my_func(self):
    print(some_module.DO_IMPORT)
    if some_module.DO_IMPORT:
        import other_module  # 把导入移到函数内
        print(other_module.OTHER_VAR)
        return True
    return False

对应的测试代码修正语法问题后就能正常跑:

from unittest.mock import patch, Mock
import unittest
import my_code

class TestMyCode(unittest.TestCase):
    @patch('my_code.other_module', OTHER_VAR='Other Var')
    @patch('my_code.some_module', DO_IMPORT=True)
    def test_my_func(self, *_):
        ret = my_code.my_func(self)
        self.assertTrue(ret)

方案3:在导入my_code前先patch

另一种思路是,确保import my_code发生在patch生效之后,这样模块加载时DO_IMPORT已经是True,条件导入会直接执行:

修改后的测试代码:

from unittest.mock import patch, Mock
import unittest

class TestMyCode(unittest.TestCase):
    @patch('my_code.some_module', DO_IMPORT=True)
    @patch('my_code.other_module', OTHER_VAR='Other Var')
    def test_my_func(self, *_):
        # 把import放到patch上下文里,确保导入时DO_IMPORT已经是True
        import my_code
        ret = my_code.my_func(self)
        self.assertTrue(ret)

这三种方案都能解决你的问题,选哪种看你是否愿意修改原代码,以及测试场景的需求。

内容的提问来源于stack exchange,提问作者Shubham Vadhera

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:29:03