使用Python 'mock'(Django)模拟类时遇到困难
我在一个django项目中使用python的“mock”模块来模拟类和函数。我的项目结构是:
Project name --> 'hello'
App1 ----> hello
App2 ----> hello_world
App3 ----> bye
‘hello’文件夹里只有tests.py和settings.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"
# ...