pytest - 使用补丁作为装饰器来修补常量

pytest - using patch as a decorator to patch a constant

我有一个对象 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 替换。

这与 documented:

的行为一致

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

... If patch() is used as a decorator and new is omitted, the created mock is passed in as an extra argument to the decorated function.

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

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

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

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

伙计们,参数的顺序很重要,所以首先模拟然后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