python class 方法模拟失败

python class method mocking failure

试图理解 mocking/patching 并且我有一个包含三个文件的 restful API 项目(仅供参考,我正在使用 flask)

  1. class1.py
  2. domain.py
  3. test_domain.py

class1.py 文件内容:

class one:
    def addition(self):
       return 4+5

domain.py 文件内容:

from class1 import one

class DomainClass(Resource):

    def post(self):

        test1 = one()
        val = test1.addition()

        return {'test' : val } 

test_domain.py文件内容:

import my_app
from flask_api import status
from mock import patch

app = my_app.app.test_client()

def test_post():
    with patch('domain.one') as mock:
        instance = mock.return_value
        instance.addition.return_value = 'yello'

    url = '/domain'
    response = app.post(url)
    print response.data

    assert status.HTTP_200_OK == response.status_code
    assert mock.called

对于我的 test_domain.py 文件,我也试过这个...

@patch('domain.one')
def test_post(mock_domain):
    mock_domain.addition.return_value = 1

    url = '/domain'
    response = app.post(url)
    print response.data

    assert status.HTTP_200_OK == response.status_code

我对 200 次通过状态的断言,但是,问题是我无法模拟或修补加法方法来给我值 1 代替 9 (4+5)。我也试过 'assert mock.called' 但它也失败了。我知道我应该在使用 'one()' 方法的 mocking/patching 中,即在 domain.py 中而不是在 class1.py 中。但是我什至尝试用 class1.one 代替 domain.one,但我仍然得到 9 而不是 1。我做错了什么?

******** 更新 我在同一问题上遇到了另一个难题,我尝试在 test_domain 文件中执行此操作而不是修补....

from common.class1 import one
def test_post():
    one.addition = MagicMock(return_value=40)

    url = '/domain'
    response = app.post(url)
    print response.data

    assert status.HTTP_200_OK == response.status_code

问题

  1. 在上面的更新中,我没有在使用它的地方做模拟(即:domain.one.addition = MagicMock(...) 它仍然有效!! !! 看来它可能正在做一个全球性的变化。为什么会这样?

  2. 在上面的例子中,'one'是模块class1.py中的一个class。如果我将此 class 'one' 更改为 class1.py 中的函数,模拟将不起作用。似乎这个驻留在模块 class1.py 中的函数 'one' 不能像这样被模拟...one.return_value = 'xyz',为什么?可以全局模拟吗?

您的代码中存在一些问题。在第一个示例中,您忘记了 patch() 应用于 with 上下文,并且在上下文结束时恢复了原始代码。按照代码应该工作:

def test_post():
    with patch('domain.one') as mock:
        instance = mock.return_value
        instance.addition.return_value = 'yello'
        url = '/domain'
        response = app.post(url)
        print response.data
        assert status.HTTP_200_OK == response.status_code
        assert mock.called
        assert response.data['test'] == 'yello'

第二个还有一个问题:如果你只想要补丁 addition 你应该使用的方法:

@patch('domain.one.addition')
def test_post(mock_addition):
    mock_addition.return_value = 1
    ...
    assert mock_addition.called
    assert response.data['test'] == 1

如果你想模拟 all one class 你应该设置 addition 方法的 return 值 模拟实例 return 由 mock_domain 调用 编辑,就像您的第一个示例:

@patch('domain.one')
def test_post(mock_domain):
    mock_addition = mock_domain.return_value.addition
    mock_addition.return_value = 1
    ...
    assert mock_addition.called
    assert response.data['test'] == 1