Using python's mock to temporarily delete an object from a dict

Question:

I am writing a test for some code that checks for a value in os.environ (I know this isn’t optimal, but I have to go with it). I would like to remove an entry from os.environ for the duration of the test. I am not sure if mock supports this. I know patch.dict can be used to modify an item, but I want the key/value pair removed. I would like something along these lines:

print os.environ
{ ... , 'MY_THING': 'foo', ... }

with mock.patch.dict.delete('os.environ', 'MY_THING'):
    # run the test
    # ( 'MY_THING' in os.environ ) should return False

# everything back to normal now    
print os.environ
{ ... , 'MY_THING': 'foo', ... }

Is there a way to perform such a feat?

Asked By: Wisco crew

||

Answers:

For deleting the item, you can simply use:

my_thing = os.environ['MY_THING']  # Gotta store it to restore it later
del os.environ['MY_THING']

And then restore it with:

os.environ['MY_THING'] = my_thing
Answered By: Spice

mock.patch.dict doesn’t quite work like your sample desired code. patch.dict is a function which requires an argument. You probably want to use it like this:

>>> import os
>>> import mock
>>> with mock.patch.dict('os.environ'):
...     del os.environ['PATH']
...     print 'PATH' in os.environ
...
False
>>> print 'PATH' in os.environ
True
Answered By: bmhkim

For those using Pytest, note that the answers involving context-managers do not work. Instead, Pytest provides a built-in fixture for Mocker, which automatically assumes a context-manager roll:

import os

def test_before_change():
    print('before change: ' + os.environ['PATH'])

def test_env_change(mocker):
    mock.patch.dict(os.environ)
    del os.environ['PATH']
    print('PATH would go here...if I had one! ' + os.environ['PATH']) 


def test_before_change():
    print('after change: ' + os.environ['PATH'])


# now run the pytest
Answered By: FaeTheWolf