简体   繁体   中英

How can I patch a ConfigParser key/value?

When I use the following code:

from unittest import mock
import configparser

configtext = '''
[SECTION]
whatever=True
'''

config = configparser.ConfigParser()
config.read_string(configtext)


def test_fails():
    expected_value = 'fnord'
    with mock.patch.dict(config, {'db': expected_value}):
        assert config['db'] is expected_value

My test fails because AttributeError: 'str' object has no attribute 'items' .

This is not at all what I expected. Obviously I would expect it to set the value like I want... but apparently config is only dict-ish, unfortunately.

How can I patch this so config['db'] is the value I want, just for the lifetime of my test?

It appears that the problem is that I had a slight misunderstanding. Although ConfigParser looks dict-like, it isn't actually. The stack trace holds evidence of this:

    def test_fails():
        expected_value = 'whatever'
>       with mock.patch.dict(config, {'db': expected_value}):

test.py:15: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/lib/python3.5/unittest/mock.py:1593: in __enter__
    self._patch_dict()
/usr/lib/python3.5/unittest/mock.py:1619: in _patch_dict
    in_dict[key] = values[key]
/usr/lib/python3.5/configparser.py:969: in __setitem__
    self.read_dict({key: value})
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <configparser.ConfigParser object at 0x7f1be6d20f98>, dictionary = {'db': 'whatever'}
source = '<dict>'

Note that it's trying to do a read_dict here. That's because it's expecting to have a section-ish format:

>>> parser = configparser.ConfigParser()
>>> parser.read_dict({'section1': {'key1': 'value1',
...                                'key2': 'value2',
...                                'key3': 'value3'},
...                   'section2': {'keyA': 'valueA',
...                                'keyB': 'valueB',
...                                'keyC': 'valueC'},
...                   'section3': {'foo': 'x',
...                                'bar': 'y',
...                                'baz': 'z'}
... })

From the docs

Having a single-key access is not possible. To get this example to work, you have to do the following:

with mock.patch.dict(config, {'db': {'db': expected_value}}):
    # rest of code

Note: Values will be converted to their stringish counterparts. So if you are trying to store an actual database connection (or similar) here, it won't work.

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