简体   繁体   中英

How to mock.patch a plain dictionary in python?

How do I mock.patch a plain dictionary {} ?

I would like to check if the headers is set to {'Content-Type': 'application/json'}.

def get(self):
    result = Spider.get_news_urls()
    for k, v in result.iteritems():
        response = requests.get(v)
        xml = response.text()
        headers = {'Content-Type': 'application/json'}
        data = ''
        taskqueue.Task(url='/v1/worker', headers=headers, payload=json.dumps(data)).add(queue_name='itagnewstasks')
    return 'success', 200

The following unit test seems to successfully patch dict. But I have a {}, which I need to patch.

@mock.patch('__builtin__.dict')
@mock.patch('requests.get')
def test_header_is_set_to_json(self, req_get, x):
    gen = Generator()
    gen.get()
    x.assert_called_with()

I suppose an alternative way would be to mock patch taskqueue.Task() and compare if it was called with headers= {'Content-Type': 'application/json'} as a parameter.

The headers you seek to mock are constructed within the method you are testing, so mocking the taskqueue.Task call would be much easier. If you were passing the header dict into the method then you could just hold onto a copy and check that it has been updated as you expect.

You can usepatch.dict to mock a dictionary:

>>> foo = {}
>>> with patch.dict(foo, {'newkey': 'newvalue'}):
...     assert foo == {'newkey': 'newvalue'}
...
>>> assert foo == {}

Ran in to an issue with patch.dict today.

patch.dict rolls back the whole dict at __exit__ ... not just the patched values. if this isn't the behavior you want, you might want to use a patcher that's more selective.

This works the same as patch.dict , but it only restores the keys you patched.

class DictPatch:
    def __init__(self, obj, patch):
        self.obj = obj
        self.patch = patch
        self.save = {}
        self.pop = []

    def start(self):
        self.save = {k: v for k, v in self.obj.items() if k in self.patch}
        self.pop = [k for k in self.patch if k not in self.obj]
        self.obj.update(self.patch)
        # this allows you to do self.addCleanup(DictPatch(...)), which is nice
        return self.stop

    def stop(self):
        self.obj.update(self.save)
        for k in self.pop:
            self.obj.pop(k)

    def __enter__(self):
        self.start()

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.stop()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM