Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python mock and libraries that are not installed

I am working on software for a robot, which is normally run on the Raspberry Pi. Let's consider the imports of two files:

motor.py (runs the motors):

from RPi import GPIO as gpio

and client.py (communicates with the server and relays commands to the motors):

from rpi.motor import Motor

Both files are in a directory called rpi, which contains a __init__.py and a __main__.py. The RPi package cannot be installed on non-RPi devices. However, I still want to test the functionality of client.py.

import unittest
from unittest import mock
# Location A


class TestClient(unittest.TestCase):
    # Location B
    setUp(self):
         # Location C
         pass

Originally, I tried from rpi.client import Client at LocA, but that failed because it tried to import Motor, and then import GPIO from RPi, which doesn't exist. I also tried mock.patch("rpi.client.Motor") at LocB (including adding mock_motor after self, and imported Client at LocC, but that failed as well. I tried mocking RPi at LocA, too, but it didn't work either.

How do you mock out a library that is not installed on your system?

like image 564
Jean Nassar Avatar asked Sep 10 '15 17:09

Jean Nassar


People also ask

What is the difference between mock and MagicMock?

With Mock you can mock magic methods but you have to define them. MagicMock has "default implementations of most of the magic methods.". If you don't need to test any magic methods, Mock is adequate and doesn't bring a lot of extraneous things into your tests.

What is MagicMock Python?

MagicMock. MagicMock objects provide a simple mocking interface that allows you to set the return value or other behavior of the function or object creation call that you patched. This allows you to fully define the behavior of the call and avoid creating real objects, which can be onerous.

What is the difference between mock and patch?

Mock is a type, and patch is a context. So you are going to pass or receive Mock instances as parameters, and apply patch contexts to blocks of code. (Lowercase 'mock' is just the name of the package.) Tests and test classes are often decorated with calls to patch.

What is Side_effect in mock Python?

side_effect: A function to be called whenever the Mock is called. See the side_effect attribute. Useful for raising exceptions or dynamically changing return values. The function is called with the same arguments as the mock, and unless it returns DEFAULT , the return value of this function is used as the return value.


1 Answers

You can use patch.dict() to patch sys.modules and mock RPi module as showed in pointed documentation.

Use follow code at the top of your test module:

>>> 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'>

In Python3 you have same behavior.


In your specific case use patch.dict is little bit overkill; maybe you aren't interested in patch context and original state recover. So you can simplify it by set sys.modules["RPi"] directly:

>>> 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'>
like image 179
Michele d'Amico Avatar answered Oct 14 '22 05:10

Michele d'Amico