2015-05-07 200 views
1

我正在爲Client類的client.py編寫單元測試,它查詢API。每個測試都使用c = client.Client("apikey")實例化客戶端。一次運行一個測試可以正常運行,但可以全部運行(例如,使用py.test)我得到一個401:「例外:響應401:未經授權的訪問。請求必須包含有效的api-key。」Python單元測試模擬API密鑰

我有一個有效的API密鑰,但是這不應該包含在單元測試中。我希望能解釋爲什麼"apikey"只適用於一個查詢。更具體地說,我該如何剔除對API的調用?下面是一個例子的單元測試:

def testGetContextReturnFields(self): 
    c = client.Client("apikey") 
    contexts = c.getContext("foo") 

    assert(isinstance(contexts[0]["context_label"], str)) 
    assert(contexts[0]["context_id"] == 0) 
+1

的HTTP什麼和如何嘲笑很大程度上取決於「客戶」類的內部。畢竟,你*可以*只是模擬'Client.getContext'返回一些固定的東西,但是你只測試你配置模擬以匹配預期的輸出。 – chepner

+0

我不確定我是否理解正確:您是否想通過真正的API調用來測試'Client'?您應該信任API(您不能再測試API),只需測試您的客戶端是否進行了正確的調用。 –

+0

@ Micheled'Amico如何測試我的客戶端在不查詢API的情況下對API做出正確的查詢? – BoltzmannBrain

回答

1

分離出對API調用的測試,以及用於Client.getContext()方法。爲了明確地測試API調用,修補請求對象......

import client 
import httpretty 
import requests 
from mock import Mock, patch 
... 
def testGetQueryToAPI(self): 
    """ 
    Tests the client can send a 'GET' query to the API, asserting we receive 
    an HTTP status code reflecting successful operation. 
    """ 
    # Arrange: patch the request in client.Client._queryAPI(). 
    with patch.object(requests, 'get') as mock_get: 
    mock_get.return_value = mock_response = Mock() 
    mock_response.status_code = 200 

    # Act: 
    c = client.Client() 
    response = c._queryAPI("path", 'GET', {}, None, {}) 

    # Assert: 
    self.assertEqual(response.status_code, 200) 

# Repeat the same test for 'POST' queries. 

以及測試getContext(),模擬出與httpretty ...

@httpretty.activate 
def testGetContextReturnFields(self): 
    """ 
    Tests client.getContext() for a sample term. 
    Asserts the returned object contains the corrcet fields and have contents as 
    expected. 
    """ 
    # Arrange: mock JSON response from API, mock out the API endpoint we expect 
    # to be called. 
    mockResponseString = getMockApiData("context_foo.json") 
    httpretty.register_uri(httpretty.GET, 
         "http://this.is.the.url/query", 
         body=mockResponseString, 
         content_type="application/json") 

    # Act: create the client object we'll be testing. 
    c = client.Client() 
    contexts = c.getContext("foo") 

    # Assert: check the result object. 
    self.assertTrue(isinstance(contexts, list), 
    "Returned object is not of type list as expected.") 
    self.assertTrue(("context_label" and "context_id") in contexts[0], 
    "Data structure returned by getContext() does not contain" 
    " the required fields.") 
    self.assertTrue(isinstance(contexts[0]["context_label"], str), 
    "The \'context_label\' field is not of type string.") 
    self.assertEqual(contexts[0]["context_id"], 0, 
    "The top context does not have ID of zero.")