python unittest 的设置函数不使用在 class 上声明的模拟
setUp function for python unittest doesn't use mocks declared over the class
所以我正在编写单元测试,但在使用 setUp 函数时遇到了问题。据我所见,它应该只是在你的函数之前执行代码,因此我可以把任何重复的东西放在那里。然而,这个函数似乎并没有在整个 class 上应用我作为补丁装饰器创建的模拟。这是我希望它看起来像的一小部分:
@patch('geomet_data_registry.layer.base.get_today_and_now', new=mocked_get_date) # noqa
@patch('geomet_data_registry.layer.base.load_plugin', new=mocked_load_plugin)
@patch('geomet_data_registry.layer.base.TILEINDEX_PROVIDER_DEF', new=mocked_tileindex) # noqa
@patch('geomet_data_registry.layer.base.STORE_PROVIDER_DEF', new=mocked_store)
class TestInitBase(unittest.TestCase):
def setUp(self):
""" Code that executes before every function. """
self.maxDiff = None
self.today_date = \
datetime.now(timezone.utc).isoformat().replace('+00:00', 'Z')
mocked_get_date.return_value = self.today_date
self.base_layer = BaseLayer({'name': 'model_gem_global'})
def test_Init(self):
expected_values = {'items': [],...
base_layer_attr = self.base_layer.__dict__
self.assertDictEqual(expected_values, base_layer_attr, msg=None)
这里我模拟了收到的日期,这样它就不会影响我的测试,我模拟了 load_plugin,当使用 returns 某个插件的 class 实例时,我模拟 TileIndex,这是一个 ES TileIndex,我模拟商店,这是一个 redis 商店。如果我使用上面显示的代码,它不起作用。当我在 setUp
中实例化 class BaseLayer
时,使用了我的模拟的 none 并且我得到:
- 'receive_datetime': '2021-11-10T12:56:07.371067Z',
? ^^^
+ 'receive_datetime': '2021-11-10T12:56:07.371131Z',
? ^^^
- 'store': <MagicMock name='mock()' id='140158154534472'>,
- 'tileindex': <MagicMock name='mock()' id='140158154534472'>,
+ 'store': <BaseStore> Redis,
+ 'tileindex': <ElasticsearchTileIndex> http://localhost:9200,
然而,在你告诉我也许我的路径对于模拟或类似的东西是错误的之前,我可以向你保证一切正常,因为如果我保持一切相同代码工作,除了我重复 class 在每个测试函数中实例化。此外,如果我保持不变,它将起作用,但是我将 setUp
命名为 mySetUp
并在函数的开头调用它。
一切都是这样工作的,我已经在完全没有使用 setUp
的情况下完成了所有测试,因为我记得自己在想“这东西坏了我不会冒险在我的测试中使用这个功能".
谢谢!
问题是 mock.patch
装饰器应用于每个测试函数,并且在 setUp
期间尚未完成修补。
要对所有测试使用相同的模拟,您必须 start/stop 在 setUp
/tearDown
中模拟。这可能看起来像:
class TestInitBase(unittest.TestCase):
def setUp(self):
self.data_patcher = patch('geomet_data_registry.layer.base.get_today_and_now',
new=mocked_get_date)
self.data_patcher.start()
self.plugin_patcher = patch('geomet_data_registry.layer.base.load_plugin',
new=mocked_load_plugin)
self.plugin_patcher.start()
...
self.today_date = \
datetime.now(timezone.utc).isoformat().replace('+00:00', 'Z')
mocked_get_date.return_value = self.today_date
self.base_layer = BaseLayer({'name': 'model_gem_global'})
def tearDown(self):
self.data_patcher.stop()
self.plugin_patcher.stop()
...
诚然,这不如使用装饰器好。您仍然可以将装饰器用于 setUp
中不必修补的函数,如果有的话。
附带说明:使用 pytest
这会不那么混乱,因为您可以在同一装置中进行设置和拆卸部分。
所以我正在编写单元测试,但在使用 setUp 函数时遇到了问题。据我所见,它应该只是在你的函数之前执行代码,因此我可以把任何重复的东西放在那里。然而,这个函数似乎并没有在整个 class 上应用我作为补丁装饰器创建的模拟。这是我希望它看起来像的一小部分:
@patch('geomet_data_registry.layer.base.get_today_and_now', new=mocked_get_date) # noqa
@patch('geomet_data_registry.layer.base.load_plugin', new=mocked_load_plugin)
@patch('geomet_data_registry.layer.base.TILEINDEX_PROVIDER_DEF', new=mocked_tileindex) # noqa
@patch('geomet_data_registry.layer.base.STORE_PROVIDER_DEF', new=mocked_store)
class TestInitBase(unittest.TestCase):
def setUp(self):
""" Code that executes before every function. """
self.maxDiff = None
self.today_date = \
datetime.now(timezone.utc).isoformat().replace('+00:00', 'Z')
mocked_get_date.return_value = self.today_date
self.base_layer = BaseLayer({'name': 'model_gem_global'})
def test_Init(self):
expected_values = {'items': [],...
base_layer_attr = self.base_layer.__dict__
self.assertDictEqual(expected_values, base_layer_attr, msg=None)
这里我模拟了收到的日期,这样它就不会影响我的测试,我模拟了 load_plugin,当使用 returns 某个插件的 class 实例时,我模拟 TileIndex,这是一个 ES TileIndex,我模拟商店,这是一个 redis 商店。如果我使用上面显示的代码,它不起作用。当我在 setUp
中实例化 class BaseLayer
时,使用了我的模拟的 none 并且我得到:
- 'receive_datetime': '2021-11-10T12:56:07.371067Z',
? ^^^
+ 'receive_datetime': '2021-11-10T12:56:07.371131Z',
? ^^^
- 'store': <MagicMock name='mock()' id='140158154534472'>,
- 'tileindex': <MagicMock name='mock()' id='140158154534472'>,
+ 'store': <BaseStore> Redis,
+ 'tileindex': <ElasticsearchTileIndex> http://localhost:9200,
然而,在你告诉我也许我的路径对于模拟或类似的东西是错误的之前,我可以向你保证一切正常,因为如果我保持一切相同代码工作,除了我重复 class 在每个测试函数中实例化。此外,如果我保持不变,它将起作用,但是我将 setUp
命名为 mySetUp
并在函数的开头调用它。
一切都是这样工作的,我已经在完全没有使用 setUp
的情况下完成了所有测试,因为我记得自己在想“这东西坏了我不会冒险在我的测试中使用这个功能".
谢谢!
问题是 mock.patch
装饰器应用于每个测试函数,并且在 setUp
期间尚未完成修补。
要对所有测试使用相同的模拟,您必须 start/stop 在 setUp
/tearDown
中模拟。这可能看起来像:
class TestInitBase(unittest.TestCase):
def setUp(self):
self.data_patcher = patch('geomet_data_registry.layer.base.get_today_and_now',
new=mocked_get_date)
self.data_patcher.start()
self.plugin_patcher = patch('geomet_data_registry.layer.base.load_plugin',
new=mocked_load_plugin)
self.plugin_patcher.start()
...
self.today_date = \
datetime.now(timezone.utc).isoformat().replace('+00:00', 'Z')
mocked_get_date.return_value = self.today_date
self.base_layer = BaseLayer({'name': 'model_gem_global'})
def tearDown(self):
self.data_patcher.stop()
self.plugin_patcher.stop()
...
诚然,这不如使用装饰器好。您仍然可以将装饰器用于 setUp
中不必修补的函数,如果有的话。
附带说明:使用 pytest
这会不那么混乱,因为您可以在同一装置中进行设置和拆卸部分。