2012-09-07 59 views
3

我正在嘗試使用模擬python庫,並決定使用裝飾器隱藏一些重複操作,以便用相應的替換方法設置mock side_effect vars。如何在unittest lib中使用python模擬庫和裝飾器?

到目前爲止,我有下面的代碼,它沒有進入測試,它基本上什麼都不做。有想法該怎麼解決這個嗎?謝謝!

import unittest 
from mock import patch 

# Replacement method for requests.get call 
def mock_requests_get(url=None, **kwargs): 
    if url == URL1: 
     return {'url':url, 'status_code':200, 'status':'success'} 

    if url == URL2: A 
     return {'url':url, 'status_code':403} 

# Replacement method for requests.post call 
def mock_requests_post(url, data=None, **kwargs): 
    if url == URL1 and data['data']=='go': 
     return {'url':url, 'status_code':200, 'status':'success'} 

    if url == URL2 and data['data']!='gogo': 
     return {'url':url, 'status_code':403} 

# Decorator which sets mock replacement methods 
def mock_type(method=''): 
    def _mock(func): 
     def _decorator(mock_get, mock_post, *args, **kwargs): 
      print method 
      if method == 'GET': 
       mock_get.side_effect = mock_requests_get 
      if method == 'POST': 
       mock_post.side_effect = mock_requests_post 
      func(mock_get, mock_post, *args, **kwargs) 
     return _decorator 
    return _mock 

@patch('requests.post') 
@patch('requests.get') 
class TestKeywordsApi(unittest.TestCase): 

    def setUp(self): 
     self.ka = KeywordsApi() 

    @mock_type('GET') 
    def test_get(self, mock_get, mock_post): 
     # Replace this code in mock_type decorator: 
     #mock_get.side_effect=mock_requests_get 

     print self.ka.get(URL1) 
     print self.ka.get(URL2) 

     # Do asserts 

    @mock_type('POST') 
    def test_post(self, mock_get, mock_post): 
     # Replace this code in mock_type decorator: 
     #mock_post.side_effect=mock_requests_post 

     print self.ka.post(URL1, {'data':'go'}) 
     print self.ka.post(URL2, {'data':'go'}) 

     # Do asserts 

回答

2

確保替換執行命名空間中的函數。取決於進口,您當前的代碼可能會或可能不會取代您認爲正在取代的內容。以下是我相信你正在嘗試做的事情。

import kwmodule 
import unittest, mock 

def mock_requests_get(url=None, **kwargs): 
    "Replacement method for requests.get call" 
    pass 

def mock_requests_post(url, data=None, **kwargs): 
    "Replacement method for requests.post call" 
    pass 

@mock.patch('kwmodule.requests.post', mock_requests_post) 
@mock.patch('kwmodule.requests.get', mock_requests_get)  
class TestKeywordsApi(unittest.TestCase): 
    def setUp(self): 
     self.ka = kwmodule.KeywordsApi() 

然而,你可能會與替換得到&後與autospecced MagicMock對象更成功。如果這不適合你,然後使用您自己的定製替換。

例如,如果您知道調用「get」的次序,則下面的修補程序修飾器將工作。

return_values = [{'url':url, 'status_code':200, 'status':'success'}, 
       {'url':url, 'status_code':403}, 
       AssertionError('Unexpected call.')] 

@mock.patch('kwmodule.requests.get', autospec=True, side_effect=return_values) 

這將返回一個「成功」的情況在第一次被調用時,一個錯誤的第二次,它會拋出一個AssertionError,如果它被稱爲第三次。十次中的九次,我使用side_effect而不是編寫自己的返回生成函數。