python mock和未安装的库

Jea*_*sar 8 python unit-testing mocking python-3.x python-unittest

我正在研究机器人的软件,它通常在Raspberry Pi上运行.让我们考虑两个文件的导入:

motor.py (运行电机):

from RPi import GPIO as gpio
Run Code Online (Sandbox Code Playgroud)

client.py(与服务器通信并将命令传递给电机):

from rpi.motor import Motor
Run Code Online (Sandbox Code Playgroud)

这两个文件都在一个名为的目录中rpi,其中包含a __init__.py和a __main__.py.该RPi软件包无法安装在非RPi设备上.但是,我仍然想测试它的功能client.py.

import unittest
from unittest import mock
# Location A


class TestClient(unittest.TestCase):
    # Location B
    setUp(self):
         # Location C
         pass
Run Code Online (Sandbox Code Playgroud)

最初,我尝试from rpi.client import Client了LocA,但是失败了,因为它试图导入Motor,然后从RPi导入GPIO,这是不存在的.我也尝试mock.patch("rpi.client.Motor")过LocB(包括在LocC mock_motor之后添加self,并Client在LocC中导入,但也失败了.我也尝试RPi在LocA上进行模拟,但它也没有用.

你如何模拟你的系统上没有安装的库?

Mic*_*ico 7

您可以使用patch.dict()补丁sys.modules和模拟RPi模块,如尖端文档中所示.

使用测试模块顶部的以下代码:

>>> from mock import MagicMock, patch
>>> mymodule = MagicMock()
>>> patch.dict("sys.modules", RPi=mymodule).start()
>>> from RPi import GPIO as gpio
>>> gpio
<MagicMock name='mock.GPIO' id='139664555819920'>
>>> import os
>>> os
<module 'os' from '/usr/lib/python2.7/os.pyc'>
Run Code Online (Sandbox Code Playgroud)

在Python3中,您有相同的行为.


在您的具体情况下,使用patch.dict有点矫枉过正; 也许你对补丁上下文和原始状态恢复不感兴趣.所以你可以通过sys.modules["RPi"]直接设置来简化它:

>>> from unittest.mock import MagicMock
>>> mymodule = MagicMock()
>>> import sys
>>> sys.modules["RPi"] = mymodule
>>> from RPi import GPIO as gpio
>>> gpio
<MagicMock name='mock.GPIO' id='140511459454648'>
>>> import os
>>> os
<module 'os' from '/usr/lib/python3.4/os.py'>
Run Code Online (Sandbox Code Playgroud)