如何在Python2.7中防止导入(并获取模块的模拟)

6
我正在为mymodule中的MyClass编写单元测试,该模块使用keras.models.load_model。每次我运行我的单元测试时导入keras库会花费几秒钟,并打印消息:“Using TensorFlow backend.” 这种行为非常烦人。在Python2.7中有可能防止导入模块(并使用Mock())吗?

mymodule.py:

from keras.models import load_model

class MyClass:
    def __init__(self):
    """I use load_model here"""
...

test_mymodule.py

import unittest

from mock import Mock, MagicMock, patch

from mymodule import MyClass

class MyClassInitializationTestCase(unittest.TestCase):
    def test_my_super_test(self):
...
1个回答

5

虽然我不熟悉keras库,但我认为您可以使用MagicMock和模块补丁的组合来使测试工作。

mymodule.py:

import keras


class MyClass(object):
    def __init__(self):
        """I use load_model here"""
        self.example = keras.models.load_model()

test_mymodule.py:

import unittest
import sys
from mock import Mock, MagicMock, patch

sys.modules['keras'] = MagicMock() # as to be done before importing mymodules
from mymodule import MyClass

class MyClassInitializationTestCase(unittest.TestCase):

    @patch('keras.models.load_model')
    def test_my_super_test(self, mock_load_model):
        """ super test """
        fake_return_value = "bar"
        mock_load_model.return_value = fake_return_value
        foo = MyClass()
        self.assertEqual(foo.example, fake_return_value)
        mock_load_model.assert_called_once()

当我运行测试时,得到了预期的结果:
$ nosetests
.
----------------------------------------------------------------------
Ran 1 test in 0.016s

OK

我会尽量解释得更详细一些(我不是单元测试或模拟方面的专家)。首先,您会注意到我已更改了您的keras库的导入方式。这只是为了避免模拟keras,然后是keras.models,最后是keras.models.load_model。我将MagicMock添加到了我的可用模块中(我没有安装它)。在导入mymodule之前,必须在导入keras之前使用MagicMock。
之后,我对keras.models.load_model进行了补丁,以供我的unittest test_my_super_test使用。您会收到模拟方法作为测试属性,我将属性命名为mock_load_model。您可以使用此模拟方法来定义其返回值。这就是我在第5行中所做的mock_load_model.return_value = fake_return_value。当我调用load_model时,该方法将返回fake_return_value。其余部分都是普通的unittest。
希望它能有所帮助。 对于社区的其他人,请纠正我是否有什么问题或是否有更好的方法。

非常感谢。我之前尝试过执行 sys.modules['keras'] = MagicMock(),但是会引发错误。为了不改变mymodule.py文件,我更喜欢像这样模拟所有keras子模块:`sys.modules['keras'] = MagicMock()` `sys.modules['keras.models'] = MagicMock()` `sys.modules['keras.models.load_model'] = MagicMock()` - Illia Sukonnik
不错,就像我所说的那样,这也是可以完成的。如果您没有进一步的问题,请将您的问题标记为已解决。 - wilfriedroset

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接