2017-10-16 100 views
1

我剛剛在Python2.7中找到了一個模擬庫,並想單元測試我的函數。無論我讀什麼教程總是關於類。我不能讓嘲笑功能工作。 該項目的結構方式是我有一些幫助功能用於從數據庫中收集和解析數據的功能。我想模擬數據庫功能和查詢功能。對於簡單的情況下,它看起來是這樣的:unittest模擬函數輸出

import unittest 
import mock 

def queryFnc(arg=0): 
    # imitate returned result from a query 
    if arg == 0: 
     return "queryFunc 0" 
    else: return "queryFunc 1" 

def parsingFunc(): 
    # function will parse result returned from a query 
    myString = queryFnc().upper() 
    return myString 

class Test(unittest.TestCase): 
    def test_queryFunc0(self): 
     self.assertEquals("queryFunc 0", queryFnc(arg=0)) 
    def test_queryFunc1(self): 
     self.assertEquals("queryFunc 1", queryFnc(arg=1)) 
    @mock.patch('.queryFnc', return_value='queryMock') 
    def test_queryMock(self, queryFnc): 
     self.assertEquals('queryMock', queryFnc()) 

    def test_parsingFunc(self): 
     self.assertEquals('QUERYFUNC 0', parsingFunc()) 
    @mock.patch('.queryFnc', return_value='queryMock') 
    def test_parsingFuncMock(self): 
     self.assertEquals('QUERYMOCK', parsingFunc()) 

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

我預計@mock.patch將取代功能上的電話,但我可以得到它的工作。我有這樣的錯誤:

====================================================================== 
ERROR: test_queryMock (__main__.Test) 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "\site-packages\mock\mock.py", line 1297, in patched 
    arg = patching.__enter__() 
    File "\site-packages\mock\mock.py", line 1353, in __enter__ 
    self.target = self.getter() 
    File "\site-packages\mock\mock.py", line 1523, in <lambda> 
    getter = lambda: _importer(target) 
    File "\site-packages\mock\mock.py", line 1206, in _importer 
    thing = __import__(import_path) 
ValueError: Empty module name 

是有另一個函數中使用不同功能的結果呢? 我受限於使用Python2.7

回答

1

The basic principle is that you patch where an object is looked up。您有幾種可能性使用mock作業,with比賽經理和@mock.patch裝飾者。我附上了一些包含打印語句的代碼,用於顯示函數何時查找原始文件以及模擬對象的位置。

# CASE 1 taking query as mock inside test_ function 
def test_queryMock1(self): 
    queryFnc = mock.Mock(return_value = 'case1') 
    print("Case 1 inside test_ after mock assignemnt", queryFnc(), queryFnc(1)) 
    self.assertEquals('case1', queryFnc(1)) 
print("Case1 after outside", queryFnc(), queryFnc(1)) 

# CASE 2 contest management with 
def test_queryMock2(self): 
    print("Case 2 inside test", queryFnc(), queryFnc(1)) 
    with mock.patch('__main__.queryFnc', return_value='case2'): 
     print("Case 2 after with", queryFnc(), queryFnc(1)) 
     self.assertEquals('case2', queryFnc()) 
print("Case 2 outside", queryFnc(), queryFnc(1)) 

# CASE 3 patching 
@mock.patch('__main__.queryFnc', return_value='case3') 
def test_queryMock3(self, *args): 
    self.assertEquals('case3',queryFnc()) 

# CASE 4 using contest management for nested function 
def test_InsideWith(self): 
    print("Case 4 inside test_", queryFnc(), queryFnc(1)) 
    #with mock.patch('__main__.queryFnc', side_effect=mockText) as mock_function_obj: 
    with mock.patch('__main__.queryFnc', return_value='case4'): 
     print("Case 4 inside with", queryFnc(), queryFnc(1)) 
     self.assertEquals('CASE4', parsingFunc()) 
print("Case 4 outside", queryFnc(), queryFnc(1)) 

# CASE 5 using patch decorator 
@mock.patch('__main__.queryFnc', return_value='case5') 
def test_Patch(self, *args): 
    print("Case 5 inside test_ after patch", queryFnc(), queryFnc(1)) 
    self.assertEquals('CASE5', parsingFunc()) 
    print("Case 5 inside test_, assert", queryFnc(), queryFnc(1)) 
print("Case 5 outside", queryFnc(), queryFnc(1)) 

請注意,在修補程序中,模塊指定爲您要修補的地方__main__。如果您嘗試使用模塊名稱,則可以看到它如何更改修補程序行爲。