简体   繁体   English

python类方法模拟失败

[英]python class method mocking failure

Trying to understand mocking/patching and I have a restful API project with three files (FYI, I'm using flask) 试图理解模拟/补丁,我有一个宁静的API项目,其中包含三个文件(仅供参考,我正在使用flask)

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

class1.py file content: class1.py文件内容:

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

domain.py file content: domain.py文件内容:

from class1 import one

class DomainClass(Resource):

    def post(self):

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

        return {'test' : val } 

test_domain.py file content: 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

For my test_domain.py file, I've also tried this... 对于我的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

My assert for the status of 200 passes, however, the problem is that I'm not able to mock or patch the addition method to give me value of 1 in place of 9 (4+5). 我对200个通过状态的主张是,但是,问题是我无法模拟或修补加法以使我的值为1而不是9(4 + 5)。 I also tried doing 'assert mock.called' and it failes as well. 我也尝试做“断言嘲讽”,它也失败了。 I know I should be mocking/patching where the 'one()' method is used, ie in domain.py not in class1.py. 我知道我应该在使用'one()'方法的地方进行模拟/修补,即在domain.py中而不是在class1.py中。 But I tried even mocking class1.one in place of domain.one and I still kept getting 9 and not 1. What am I doing wrong ? 但是我什至尝试模仿class1.one代替domain.one,但我仍然一直得到9而不是1。我在做什么错?

******** Update I've another dilemma on the same issue, I tried doing this in the test_domain file instead of patching.... ********更新我在同一问题上遇到了另一个难题,我尝试在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

Question

  1. In update above, I did not do a mock at the place where it is used (ie: domain.one.addition = MagicMock(...) and it still worked !!!! It seems it may be doing a global change. Why did this work ? 在上面的更新中,我没有在使用它的地方进行过模拟(即:domain.one.addition = MagicMock(...),并且仍然有效!!!!看来它正在进行全局更改。为什么这项工作?

  2. In the above example, 'one' is a class in the module class1.py. 在上面的示例中,“ one”是模块class1.py中的类。 If I change this class 'one' to a function in class1.py, mocking does not work. 如果我将此类“ one”更改为class1.py中的函数,则无法进行模拟。 It seems this function 'one' residing in module class1.py can not be mocked like this...one.return_value = 'xyz', why? 似乎不能像这样嘲笑模块class1.py中的函数“ one” ... one.return_value ='xyz',为什么? Can it be mocked globally ? 可以在全球范围内嘲笑吗?

There are some issues in your code. 您的代码中存在一些问题。 In the first example you forgot that patch() is applied in with context and the original code is recovered when the context end. 在第一个示例中,您忘记了patch() with上下文with应用,并且上下文结束时恢复了原始代码。 Follow code should work: 遵循代码应该可以工作:

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'

The second one have an other issue: if you want patch just addition method you should use: 第二个还有另一个问题:如果只想addition补丁,则应该使用:

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

If you want mock all one class you should set the return value of addition method of mock instance returned by mock_domain call like in your first example: 如果要模拟所有one ,则应像第一个示例中那样设置mock_domain调用返回模拟实例addition的返回值:

@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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM