2016-03-03 122 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()