2015-03-02 94 views
0

我正在为Django基于类的视图编写单元测试。Django UnitTest with Mock

class ExampleView(ListView): 

    def get_context_data(self, **kwargs): 
     context = super(EampleView, self).get_context_data(**kwargs) 
     ## do something else 

    def get_queryset(self, **kwargs): 
     return self.get_data() 

    def get_data(self): 
     call_external_API() 
     ## do something else 

的关键问题是get_data()call_external_API()

当我编写单元测试时,我并不想调用外部API来获取数据。首先,这会耗费我的钱;其次,我可以在另一个测试文件中轻松测试该API。

我也可以很容易地测试这个get_data()方法只有一个单元测试,并模拟输出call_external_API()

然而,当我测试这整个基于类的观点,我只是会做

self.client.get('/example/url/') 

,并检查状态代码和上下文数据来验证。

在这种情况下,我在测试整个基于类的视图时如何模拟这个call_external_API()

+0

不知道你的两种情况有什么不同。为什么你不能以同样的方式嘲笑它? – 2015-03-02 20:27:53

回答

1

你在找什么是patch from unittest.mock。您可以将call_external_api()修补为MagicMock()对象。

也许你想在课堂上为所有的测试打补丁call_external_api()patch给你essentialy双向做

  • 装饰测试类
  • 使用start()stop()setUp()tearDown()分别为

修饰类由patch装饰就像是装饰所有测试方法(详细信息请参阅文档),实施将非常简洁。后续示例假设您的视图位于my_view模块中。

@patch("my_view.call_external_api", autospec=True) 
class MyTest(unittest.TestCase): 
    def setUp(self): 
     self.client = Client() 

    def test_get_data(self, mock_call_external_api): 
     self.client.get('/example/url/') 
     self.assertTrue(mock_call_external_api.called) 

更深沉的例子,可以建立并可以检查你怎么称呼mock_call_external_api并设置返回值或副作用的API。

我不给约开始任何例子和停止的方式来做到这一点(我真的不喜欢它),但我想花一些时间在两个细节

  1. 我假设在你my_view模块定义call_external_api或者您from my_API_module import call_external_api导入它,否则你要在Where to patch
  2. 我用autospec=True一些注意事项:恕我直言,应该在每个补丁调用中使用和documentation解释为什么很好
+0

这是我正在寻找的答案。谢谢! – 2015-03-03 15:13:41

0

的东西测试归类基于视图像这样的时候你可以嘲笑call_external_api()方法:

import modulea 
import unittest 
from mock import Mock 

class ExampleTestCase(unittest.TestCase): 

    def setUp(self): 
     self.call_external_api = modulea.call_external_api 

    def tearDown(self): 
     modulea.call_external_api = self.call_external_api 

    def get_data(self): 
     modulea.call_external_api = Mock(return_value="foobar") 
     modulea.call_external_api() 
     ## do something else