我可以使用装饰器修补对象方法吗

时间:2019-03-06 09:07:14

标签: python-3.x mocking pytest

挑战:修补/模拟远程类中的方法调用以返回已知数据。

我进行了一系列的测试,如下所示:

@pytest.mark.gen_test
def test_assignment5(app):
    with patch.object(BaseHandler, 'get_current_user') as mock_user:
        mock_user.return_value = {"name": '1_kiz'}
        with patch.object(BaseHandler, 'get_auth_state') as mock_state:
            mock_state.return_value = { "course_id": "course_2",
                                        "course_role": "Instructor",
                                        "course_title": "A title",
                                    }
            r = yield async_requests.get(app.url + "/assignment?course_id=course_2&assignment_id=assign_a")
    assert r.status_code == 200
    response_data = r.json()   
    assert response_data["success"] == False
    assert response_data["note"] == "Assignment assign_a does not exist"   

({app是我的应用程序的核心方法,get_current_userget_auth_state使用应用程序范围之外的信息来获取价值,因此需要 Fudget

...重复的with句段冒犯了我对美观代码的敏感性。

我知道我可以将返回值字典拉到顶级变量,这样可以减少重复代码的 some ,但是我仍然在每重复一次with patch.object时间。

阅读https://docs.python.org/dev/library/unittest.mock.html#unittest.mock.patch我知道我可以简单地装饰每个测试

user_kiz = { ... }
auth_inst = { ... }

....

@pytest.mark.gen_test
@patch('BaseHandler.get_current_user', return_value = user_kiz)
@patch('BaseHandler.get_auth_state', return_value = auth_inst)
def test_assignment5a(app, kiz):
    r = yield async_requests.get(app.url + "/assignment?course_id=course_2&assignment_id=assign_a")
    assert r.status_code == 200
    response_data = r.json()   
    assert response_data["success"] == False
    assert response_data["note"] == "Assignment assign_a does not exist"

给我一​​个ModuleNotFoundError: No module named 'BaseHandler'错误。

是否有一种方法可以修补/模拟远程类中的方法调用,从而允许我为每个调用设置current_userauth_state字典?

(最终,我还将需要针对不同的用户和不同的auth_states进行测试)

1 个答案:

答案 0 :(得分:0)

要替换这样的呼叫:

with patch.object(a, 'b', c):

使用装饰器,您将使用:

@patch.object(a, 'b', c)

您已切换为字符串形式

@patch(..., ...)

字符串形式要求将完整的导入路径作为第一个参数