【问题标题】:pytest - using patch as a decorator to patch a constantpytest - 使用补丁作为装饰器来修补常量
【发布时间】:2021-11-21 14:24:48
【问题描述】:

我有一个对象MyObject,它使用mymodule.constants.MYCONSTANT 中定义的常量。我可以像这样使用上下文管理器成功修补常量:

import pytest
from unittest.mock import patch

def test_constant(self):
    with patch('mymodule.constants.MYCONSTANT', 3):
        MyObject()

但是,我不知道如何使用 patch 作为装饰器来使用等效补丁:

@patch('mymodule.constants.MYCONSTANT', 3)
def test_constant(self, mock_constant):
     MyObject()

上述操作失败并出现fixture mock_constant not found 错误。我尝试使用

@patch('mymodule.constants.MYCONSTANT', return_value=3)

但是MYCONSTANT 不会被替换为 3。

【问题讨论】:

  • 如果您在装饰器中提供替换值,则不会将任何参数插入到测试函数中,因此如果您删除示例中的 mock_constant 参数,它可能会起作用。 return_value 仅适用于函数调用或类实例化的结果。

标签: python mocking pytest decorator patch


【解决方案1】:

这与documented 的行为一致:

unittest.mock.patch(target, new=DEFAULT, spec=None, create=False, spec_set=None, autospec=None, new_callable=None, **kwargs)

...如果patch() 用作装饰器并且省略了new,则创建的模拟将作为额外参数传递给装饰函数。

因此,如果您想将额外参数传递给修饰函数,请不要设置 new 参数:

@patch('mymodule.constants.MYCONSTANT')
def test_constant(self, mock_constant):
    ...

设置new 参数意味着不会传递额外的参数:

@patch('mymodule.constants.MYCONSTANT', 3)
def test_constant(self):
    ...

【讨论】:

    【解决方案2】:

    参数的顺序很重要,所以首先模拟然后fixtures,否则它仍然会抛出同样的错误。

    @patch('server.app.UserValidator')
    def test_first_mocks(self,mock_user_validator:MagicMock,client_fixture:FlaskClient):
        # Arrange
        input = {'password':'internal','username':'error'}
        mock_user_validator.side_effect = ValueError('testing')
        # Act
        response = client_fixture.post('/api/users',json=input)
        # Assert
        mock_user_validator.assert_called_once()
        assert response.status_code == 500
    

    【讨论】:

      猜你喜欢
      • 2018-12-30
      • 2017-01-31
      • 2021-12-20
      • 1970-01-01
      • 2021-07-19
      • 1970-01-01
      • 1970-01-01
      • 2023-03-15
      • 1970-01-01
      相关资源
      最近更新 更多