python类方法模拟失败

时间:2015-05-07 05:11:00

标签: python flask mocking patch

尝试理解模拟/修补,我有一个包含三个文件的宁静API项目(仅供参考,我正在使用烧瓶)

  1. class1.py
  2. domain.py
  3. test_domain.py
  4. 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)。我也试过'断言mock.called',它也很脆弱。我知道我应该使用'one()'方法进行模拟/修补,即在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中的一个类。如果我将这个类'one'更改为class1.py中的函数,则mocking不起作用。似乎这个函数'one'驻留在模块class1.py中不能像这样嘲笑... one.return_value ='xyz',为什么?可以在全球范围内嘲笑吗?

1 个答案:

答案 0 :(得分:2)

您的代码中存在一些问题。在第一个示例中,您忘记了在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

如果你想要模拟所有one,你应该设置addition调用模拟实例的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