2016-03-03 62 views
3

我有一个返回多个值的python函数。我的功能:模拟具有多个返回值的python函数

def myExampleFunction(a,b) 
    # here is my code 
    return name, number1, number2 


def FunctionIWantToTest(self): 
    # here is my code 
    myName, myNumber1, myNumber2 = self.myExampleFunction(a,b) 

我想给我自己的值从FunctionIWantToTest返回的值。所以,我试图用nosetest测试第二个函数,但我不知道如何模拟myExampleFunction的返回值。

我尝试这样做:

def test_mytest(self): 
    [...] 
    c.myExampleFunction = Mock() 
    c.myExampleFunction.side_effect = ["myName", 100, 200] 
    [...] 

但它不工作。当我推出nosetests时,我看到这条消息:

ValueError: too many values to unpack 

有什么想法吗?我使用python 2.7.3

+0

[文件](https://docs.python.org/3/library/unittest.mock.html#unittest。 mock.Mock):如果side_effect是一个迭代器,那么每次调用模拟器都会返回iterable中的下一个值。 – DreyFax

+0

我回应自己:为我开火的代码:c.myExampleFunction.return_value =“myName”,100,200 – myg

+0

这与Daniel的答案相同,所以请接受它。这使得有类似问题的用户更容易识别,这个答案起作用。评论中的答案很难找到。 – DreyFax

回答

5

您需要设置模拟的return_value,而不是side_effect

当实例它你可以这样做:

c.myExampleFunction = Mock(return_value=["myName", 100, 200]) 
+0

它的工作原理!感谢Daniel和DreyFax! – myg

2

只是想分享如何让这与side_effect工作。我整理了一个简化版本,以展示如何使用side_effect作为您的用例。

side_effect行为不同于RETURN_VALUE,就是当你提供一个side_effect与条目列表,你实际上说明的是,每次你模拟的方法被调用时会在列表作为它的返回值返回的每个项目。其实,这就是为什么你越来越ValueError异常:值过多解压(预计3),因为这样做:

[1, 2, 3] 

你都这么说,每次调用我的嘲笑方法,返回1,则下一次我打电话的方法,返回2,然后返回3.

考虑到这一点,如果您设置side_effect,像这样:

[('stuff1', 'stuff2', 'stuff3')] 

什么你现在说的是,对于当你打电话给side_effect的时候,列表中的第一项是返回的内容。这实际上是:

('stuff1', 'stuff2', 'stuff3') 

或者,你可以这样做:

my_test_foo.side_effect = lambda x, y: (1, 2, 3) 

模仿出你是通过采取有两个参数和返回三个值应该返回用于测试的方法。

因此,考虑到这一点,你的测试可以被构造为:

import unittest 
from unittest.mock import Mock 

from mock import patch 
from stuff import FunctionIWantToTest 


class MyTest(unittest.TestCase): 

    @patch('stuff.myExampleFunction', return_value=Mock()) 
    def test_mytest(self, m_example_function): 
     m_example_function.side_effect = [("stuff1", 100, 200)] 
     # m_example_function.side_effect = lambda x, y: ("stuff1", 100, 200) 

     a, b, c = FunctionIWantToTest() 

if __name__ == '__main__': 
    unittest.main()