如何模拟我的一个单元测试函数的输出?

时间:2012-03-15 17:19:49

标签: python django testing mocking

我有一个python(django)Web应用程序。它使用外部Web服务(Facebook Graph)。用于进行外部(http)调用的所有代码都包含在一个额外的函数(称为facebook_api)中,该函数接受一些参数并返回解析的dict(它执行一些日志记录,检查错误等)。围绕此函数,我写了一些代码。我想做一些这个代码的单元测试。

如何用一些已知的输入“模拟”这个函数?即我想提供一些输入和我的facebook_api函数的输出(即如果你看到这个输入,则返回此信息,如果是这样,则返回该信息等)。然后我想检查我的代码是否正确处理它。

我想为我的代码提供各种不同的场景(如果API开始返回这个或那个),并检查我的代码是否符合我的要求。我不想实际发出外部(http)请求。

我尝试查看一些模拟库(例如http://www.voidspace.org.uk/python/mock/),但他们总是谈论创建类对象,或者只是检查是否调用了某些东西。我看不出简单的方法来说“拦截这个函数,如果输入是A,则返回X,如果它像D一样,返回B”

3 个答案:

答案 0 :(得分:2)

我认为您正在寻找Mock's side_effect。例如

def my_facebook_api(input):
    if input=='A':
        return 'X'
    elif input=='B':
        return 'D'

facebook_api =  Mock(side_effect=my_facebook_api)

答案 1 :(得分:1)

我一直在使用mockito-python(http://code.google.com/p/mockito-python/)取得了不错的成功。它允许您使用简单的语法指定模拟的行为(直接来自他们的文档):

>>> dummy = mock()
>>> when(dummy).reply("hi").thenReturn("hello")
>>> when(dummy).reply("bye").thenReturn("good-bye")
>>> dummy.hi()
>>> dummy.reply("hi")
'hello'
>>> dummy.reply("bye")
'good-bye'

这当然要求您能够在测试期间将包含facebook_api的对象更改为模拟。

答案 2 :(得分:1)

这是mock的一个例子:

>>> import mock
>>> patcher = mock.patch('django.core.urlresolvers.reverse')
>>> reverse_mock = patcher.start()
>>> reverse_mock.return_value = "/foo/"
>>> from django.core.urlresolvers import reverse
>>> reverse('someview')
'/foo/'
>>> patcher.stop()

很少注意到: