A missing blog post image

After 4 days of struggling and having browsed half of StackOverflow answers, I’ve decided to publish a blog post accounting for the Python mocking operation described below.

While populating test cases for the archey project, I wanted to mock some subprocess.Popen calls, used in contexts like this one :

check_output(
    ['grep', '-E', '3D|VGA|Display'],
    stdin=Popen(['lspci'],
                stdout=PIPE,
                stderr=DEVNULL).stdout
).decode().split(': ')[1].rstrip()

So the first thought you might have would be something like :

@mock.patch.object(
    'module.submodule.Popen',
    'stdout',
    'Mocked string',
    create=True
)

… but this does not work, as Popen expects a file-like object to read from.

In order to sum this mess up, the problems here are :

  • subprocess.check_output call needs a readable pipe to work

  • stdout attribute is a runtime attribute of Popen return object

  • The will of not using a different mocking framework than default unittest

So the final workaround I’ve come up with is :

  • Mocking the FIFO with a temporary file

  • Writing to this file the mocked content

  • Rewinding to the beginning of the file

  • Make the Popen mock returning this file as stdout attribute

  • Running concerned tests

  • Deleting the temporary file

Everything is more or less explained in this Gist :

Any comment or improvement would be welcome :ok_hand: