很好,RemovalService如同我們計劃的一樣工作。接下來讓我們創建另一個以該對象為依賴項的服務:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#!/usr/bin/env python # -*- coding: utf-8 -*- import os import os.path class RemovalService(object): """A service for removing objects from the filesystem.""" def rm(filename): if os.path.isfile(filename): os.remove(filename) class UploadService(object): def __init__(self, removal_service): self.removal_service = removal_service def upload_complete(filename): self.removal_service.rm(filename) |
到目前為止,我們的測試已經覆蓋了RemovalService, 我們不會對我們測試用例中UploadService的內部函數rm進行驗證。相反,我們將調用UploadService的RemovalService.rm方法來進行簡單的測試(為了不產生其他副作用),我們通過之前的測試用例可以知道它可以正確地工作。
有兩種方法可以實現以上需求:
1.模擬RemovalService.rm方法本身。
2.在UploadService類的構造函數中提供一個模擬實例。
因為這兩種方法都是單元測試中非常重要的方法,所以我們將同時對這兩種方法進行回顧。
選項1: 模擬實例的方法
該模擬庫有一個特殊的方法用來裝飾模擬對象實例的方法和參數。@mock.patch.object 進行裝飾:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
#!/usr/bin/env python # -*- coding: utf-8 -*- from mymodule import RemovalService, UploadService import mock import unittestclass RemovalServiceTestCase(unittest.TestCase): @mock.patch('mymodule.os.path') @mock.patch('mymodule.os') def test_rm(self, mock_os, mock_path): # instantiate our service reference = RemovalService() # set up the mock mock_path.isfile.return_value = False reference.rm("any path") # test that the remove call was NOT called. self.assertFalse(mock_os.remove.called, "Failed to not remove the file if not present.") # make the file 'exist' mock_path.isfile.return_value = True reference.rm("any path") mock_os.remove.assert_called_with("any path") class UploadServiceTestCase(unittest.TestCase): @mock.patch.object(RemovalService, 'rm') def test_upload_complete(self, mock_rm): # build our dependencies removal_service = RemovalService() reference = UploadService(removal_service) # call upload_complete, which should, in turn, call `rm`: reference.upload_complete("my uploaded file") # check that it called the rm method of any RemovalService mock_rm.assert_called_with("my uploaded file") # check that it called the rm method of _our_ removal_service removal_service.rm.assert_called_with("my uploaded file") |
原文轉自:http://www.diggerplus.org/archives/2704