Python的Mock模拟测试介绍(4)

发表于:2014-03-21来源:DiggerPlus作者:DiggerPlus点击数: 标签:模拟测试
很好,RemovalService如同我们计划的一样工作。接下来让我们创建另一个以该对象为依赖项的服务: 12345678910111213141516171819 #!/usr/bin/env python # -*- coding: utf-8 -

  很好,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