我有一個棘手的問題,我似乎無法掌握。我是 ,目前正在編寫一個django自定義auth-backend的單元測試。在我們的 系統中,我們實際上有兩個後端:一個是內置的django後端 以及將請求發送到基於Java的API 的自定義後端,該後端以XML形式返回用戶信息。現在,我正在寫單元 測試,所以我不想在系統之外發送請求,如 ,我沒有試圖測試Java API,所以我的問題是我怎麼能 解決這個問題,並嘲笑以最穩健的方式提供副作用。乾淨地嘲笑Django Unittests的遠程服務器和API
我測試的功能是這樣的,其中URL 設置值只是針對 驗證用戶名和密碼的數據,並返回XML的Java服務器的基本URL,以及服務價值是 只是一些魔法建設的網址查詢,它不重要的 我們:
@staticmethod
def get_info_from_api_with_un_pw(username, password, service=12345):
url = settings.AUTHENTICATE_URL_VIA_PASSWORD
if AUTH_FIELD == "username":
params = {"nick": username, "password": password}
elif AUTH_FIELD == "email":
params = {"email": username, "password": password}
params["service"] = service
encoded_params = urlencode([(k, smart_str(v, "latin1")) for k, v in params.items()])
try:
# get the user's data from the api
xml = urlopen(url + encoded_params).read()
userinfo = dict((e.tag, smart_unicode(e.text, strings_only=True))
for e in ET.fromstring(xml).getchildren())
if "nil" in userinfo:
return userinfo
else:
return None
所以,我們得到的XML,解析成一個字典,如果關鍵的零存在 那麼我們可以返回字典和發揚快樂並經過認證。 顯然,一個解決方案是隻是爲了找到猴補丁在XML變量的邏輯,我發現這個答案的方式以某種方式覆蓋或 :
How can one mock/stub python module like urllib
我試圖實現類似的東西,但在細節上有是 非常粗略,我似乎無法得到這個工作。
我也拍攝到的XML響應,並把它放在一個本地文件中 測試文件夾尋找一種方法來使用,作爲傳遞到測試功能的URL參數模擬 響應的意圖, 像這樣將覆蓋網址:
@override_settings(AUTHENTICATE_URL_VIA_PASSWORD=(os.path.join(os.path.dirname(__file__), "{0}".format("response.xml"))))
def test_get_user_info_username(self):
self.backend = RemoteAuthBackend()
self.backend.get_info_from_api_with_un_pw("user", "pass")
但也需要考慮到的是, 函數定義(即「URL + encoded_params」)的URL建築邏輯。再次,我可以將 的響應文件重命名爲與連接的url相同,但這不像是一個很好的函數單元測試和更多的「作弊」,整個 事情越來越多這些解決方案一直都很脆弱,無論如何它只是一個固定裝置,這也是我想要儘量避免的東西。
我也想知道是否有一種方法可以在django開發服務器上爲xml服務,然後在那裏指向這個函數?這似乎是一個更爲理智的解決方案,但是如果這樣的事情是可能的或者明智的,那麼很多使用Google的人不會給我提供任何線索,即使如此,我也認爲這不是一種在開發環境之外運行的測試。
所以,理想情況下,我需要能夠以某種方式嘲笑「服務器」,以 採取了Java API的地方在函數調用,或以某種方式成爲 一些XML負載的功能,可以作爲其網址打開,或 monkeatch從測試本身的功能,或...
模擬庫是否有適當的工具來做這樣的事情?
http://www.voidspace.org.uk/python/mock
那麼,有兩點對這個問題1)我想解決一個乾淨的方式我 特別的問題,更重要的是2)什麼是 的最佳做法乾淨寫Django的單元 - 根據數據,Cookie等, 進行測試,以便從遠程的 API進行用戶驗證,該API位於您的域之外?
在你的情況下,你會想要模擬以下內容:'import models; self.mock('models.urlopen')',因爲它似乎是在您的模型文件'urllib import urlopen'中將它導入如下。 – Pykler
啊,那太棒了,看起來這樣的嘲笑就是票。非常感謝! – osman