使用Python 'mock'(Django)模拟类时遇到困难

0 投票
1 回答
558 浏览
提问于 2025-04-21 01:45

我在一个django项目中使用python的“mock”模块来模拟类和函数。我的项目结构是:

Project name --> 'hello'
               App1 ----> hello
               App2 ----> hello_world
               App3 ----> bye

‘hello’文件夹里只有tests.pysettings.py。‘hello_world’文件夹里有一个视图文件‘greetings.py’,内容如下:

from django.shortcuts import render
from django.http import HttpRequest,HttpResponse
from bye import views

# Create your views here.                                                                                                                                                                                   

def greet(request):
    views.saybye()
    gb_class = views.goodbye()

    print gb_class.saygoodbye()
    print 'greet called'

    return HttpResponse('hello world',content_type='application/html')

‘bye’文件夹里有一个views.py,内容是:

from django.shortcuts import render 
from django.http import HttpRequest

# Create your views here.

def saybye():
    print "goodbye world"
    return

class goodbye:
    def __init__(self):
        print "goodbye's init called"
        return

    def saygoodbye(self):
        return "goodbye.saygoodbye called"

现在,我的‘tests.py’是:

from unittest import TestCase

import mock
from mock import patch

from hello_world import greetings
import bye 

from django.test.client import RequestFactory


class TestBasic(TestCase):
    def setUp(self):
        self.var = 'abc'
        self.factory = RequestFactory()

    @patch('bye.views.goodbye')
    def test_greeting(self,mocksaybye):
        assert mocksaybye is bye.views.goodbye
        mocksaybye.saygoodbye = mock.MagicMock(return_value="mocked goodbye called")

        bye.views.goodbye()
        print mocksaybye.saygoodbye()

        assert mocksaybye.called
        assert mocksaybye.saygoodbye.called

        req = self.factory.get('/sayhello/')
        greetings.greet(req)

当我运行‘python manage.py test’时,得到的输出是:

mocked goodbye called
goodbye world
<MagicMock name='goodbye().saygoodbye()' id='60566864'>
greet called

我本来期待输出的第三行是:"mocked goodbye called",因为我理解mocksaybye类会模拟goodbye类的saygoodbye函数,并返回自定义的输出mocked goodbye called

但是,这并没有发生。为什么会这样呢?我该怎么做才能得到我想要的输出呢?

1 个回答

0

你需要使用 side_effect 方法,而不是 return_value。另外,要用 @patch.object,而不是 @patch

所以,不要用下面这段代码:

@patch('bye.views.goodbye')
def test_greeting(self,mocksaybye):
    # ...
    mocksaybye.saygoodbye = mock.MagicMock(return_value="mocked goodbye called")
    # ...

而是用这个(我还没测试过):

@patch.object('bye.views.goodbye', 'saygoodbye')
def test_greeting(self,mocksaybye):
    # ...
    mocksaybye.side_effect = lambda: "mocked goodbye called"
    # ...

撰写回答