之前定义的 rm 方法相当的简单.在盲目地删除之前,我们倾向于验证一个路径是否存在,并验证其是否是一个文件.让我们重构 rm 使其变得更加智能:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import os.path
def rm(filename):
? ?if os.path.isfile(filename):
? ? ? ?os.remove(filename)
很好.现在,让我们调整测试用例来保持测试的覆盖率.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from mymodule import rm
import mock
import unittest
class RmTestCase(unittest.TestCase):
? ?@mock.patch('mymodule.os.path')
? ?@mock.patch('mymodule.os')
? ?def test_rm(self, mock_os, mock_path):
? ? ? ?# set up the mock
? ? ? ?mock_path.isfile.return_value = False
? ? ? ?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
? ? ? ?rm("any path")
? ? ? ?mock_os.remove.assert_called_with("any path")
我们的测试用例完全改变了.现在我们可以在没有任何副作用的情况下核实并验证方法的内部功能.
将文件删除作为服务
到目前为止,我们只是将 mock 应用在函数上,并没应用在需要传递参数的对象和实例的方法上.我们现在开始涵盖对象的方法.
首先,我们将?rm ?方法重构成一个服务类.实际上将这样一个简单的函数转换成一个对象,在本质上这不是一个合理的需求,但它能够帮助我们了解?mock ?的关键概念.让我们开始重构:
#!/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)
你会注意到我们的测试用例没有太大变化:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from mymodule import RemovalService
import mock
import unittest
class RemovalServiceTestCase(unittest.TestCase):
? ?@mock.patch('mymodule.os.path')
? ?@mock.patch('mymodule.os')
? ?def test_rm(self, 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")
很好,我们知道?RemovalService ?会如预期般的工作.接下来让我们创建另一个服务,将?RemovalService ?声明为它的一个依赖:
#!/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(self, 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(self, filename):
? ? ? ?self.removal_service.rm(filename)
(编辑:ASP站长网)
|