如何在 Python 中模拟字典

Jam*_*Lin 20 python mocking

假设我有一个这样的功能:

def do_something(dict_obj):
   # access to the dict_obj then do some stuff
   eg.
   if dict_obj['doors']:
      do_something_with_doors()
   map_car_make(dict_obj['make'])
   ...

   if dict_obj['is_active']:
        do_something_else()
Run Code Online (Sandbox Code Playgroud)

我想模拟dict_obj拥有is_active元素而不关心其余的,我该怎么做?

Man*_*anu 24

如何在 Python 中模拟字典是其他人可以搜索的一个很好/直接的问题,因此:

  1. 我建议使用MagicMock而不是 Mock
  2. 重载 __getitem__
from unittest.mock import MagicMock

m = MagicMock()
d = {'key_1': 'value'}
m.__getitem__.side_effect = d.__getitem__

# dict behaviour
m['key_1'] # => 'value'
m['key_2'] # => raise KeyError

# mock behaviour
m.foo(42)
m.foo.assert_called_once_with(43) # => raise AssertionError
Run Code Online (Sandbox Code Playgroud)

相关问题:

=== 编辑 ===

作为直接复制/粘贴的功能

def mock_dict(d):
  m = MagicMock()
  m.__getitem__.side_effect = d.__getitem__
  return m
Run Code Online (Sandbox Code Playgroud)


Pet*_*one 13

对于以后遇到这个问题的人来说,还有它mock.patch.dict可以用作上下文管理器、装饰器或类装饰器。

例如:

from mock import patch

foo = {}
@patch.dict(foo, {"is_active": True})
def test():
    assert foo['is_active'] == True

Run Code Online (Sandbox Code Playgroud)

或者嘲笑os.environ我是如何遇到这个问题的:


import os
from mock import patch

@patch.dict("os.environ", {"FOO": "BAR"})
def test_env():
    assert os.environ['FOO'] == "BAR"
Run Code Online (Sandbox Code Playgroud)


era*_*ros 5

您可以使用它来使模拟行为像字典一样:

mock = mocker.MagicMock()
mock.__getitem__.side_effect = lambda x: getattr(mock, x)
Run Code Online (Sandbox Code Playgroud)

该代码mock['some_property']等于mock.some_property. 这样你仍然可以使用自动生成的Mock断言,这对断言非常有用,这就是为什么我不喜欢接受的答案。

如果您仍然需要访问字典的方法,那么代码将需要进一步的工作。