Tag Archives: Day2

unittest.mock in Python

Python is a language that allows for fast iteration. In fact, it is this fast
iteration that makes prototyping
one of its primary use cases. Because of this fast iteration, I don’t feel as
guilty about re-writing programs in Python as I would feel rewriting programs
in C or Rust.

This also makes Python both easy and satisfying to learn. It is easy in the sense
that any new concepts can be quickly incorporated into existing projects. It is
satisfying in the same sense, where newly learned concepts can be quickly put
into practice, producing immediate results.

Thus, the Adventures with Python project is a perfect way to reinforce my
passion for coding and learn more about the language itself.

Mocking

Testing applications is something that is fascinating to me. To have a test suite
that exposes stupid mistakes and easy-to-fix errors is like a golden ticket to
a successful application. Constructing good unit tests has always been challenging
for me, however. For instance, in one of my recent applications I had code to
test whether or not file-reading function succeeded.The module looked a little something like:

import filemanager # A 3rd-party library
def read(filePath):
 return filemanager.read(filePath)[5:]

The test looked a little something like:

import util.filereader
import unittest
class TestFilereader(unittest.TestCase):
 def test_read(self):
 with open('filename', 'w+') as openFile:
   openFile.write('fakercontents')
self.assertEquals(filereader.read('filename'), 'contents')

Although there is nothing immediately wrong with this code, it produces some
issues. For instance, the test relies on file creation, meaning that if it is
run with insufficient privileges, it will fail. Further, it has the nasty side
effect of messing with the file system.

That’s when I discovered unittest.mock,
Python’s way of solving this exact issue. With Mock, I could essentially mock
and alter anything pertaining to my module that could make my tests better.
If I wanted to improve the above test using mock, for instance, I could do the
following:

import util.filereader
import unittest
import mock
class TestFilereader(unittest.TestCase):
 @mock.patch('filereader.filemanager.read')
 def test_read(self, mocked_filemanager_read):
 mocked_filemanager_read.return_value = 'fakercontents'
 self.assertEquals(filereader.read('filename'), contents')
 mocked_filemanager_read.assert_called_with('filename')

This makes the test much simpler and much more robust. The test is no longer
relying on the creation of files or on the reliance of Python file-creation
libraries. It also doesn’t have any nasty side effects.

Most of my work with Mocks has been done in a professional setting, so I cannot
share any real-world code; however, I plan to use Mocks in the testing
of PyCFramework, so be on the
lookout for that if you’re looking for real-world applications.