python中mock的使用

本文介绍了可单独使用mock进行单元测试,而非仅与unittest结合。作者主要在nose框架下使用mock,阐述了mock的四个主要函数及四个assert方法,并给出相关代码示例,还提供了mock详细资料的参考文献。
    查了很多资料,很多资料都是把mock跟unittest结合在一起讲的,unittest本身是有一定难度的,其实我们完全可以单独使用mock的。参考文献1中把mock讲的很详细,只要静下心来看,必定收获很多,感谢译者的辛勤付出!参考文献2中有个pdf文档,是最详细的官方文档,大概100页,也很不错,没有深入读了,以后用到了再在这篇博客里更新。
我现在主要是在nose框架下使用的mock,mock主要有name,return_value,side_effect,和spec四个函数,其中的意义都看下面的文档吧。
四个主要的assert方法:
assert_called_with  是否调用了这个函数
assert_called_once_with  是否只调用了一次这个函数
assert_has_calls 查看方法调用的顺序
assert_any_calls  是否调用了这个函数,前两个函数只能判断离它们最近的一次调用,这个是全局的。

参见代码:
from mock import Mock, call

class Order(object):
    # instance properties
    _orderItem = "None"
    _orderAmount = 0
    _orderFilled = -1
     
    # Constructor
    def __init__(self, argItem, argAmount):
        print "Order:__init__"
         
        # set the order item
        if (isinstance(argItem, str)):
            if (len(argItem) > 0):
                self._orderItem = argItem
         
        # set the order amount
        if (argAmount > 0):
            self._orderAmount = argAmount
         
    # Magic methods
    def __repr__(self):
       # assemble the dictionary
        locOrder = {'item':self._orderItem, 'amount':self._orderAmount}
        return repr(locOrder)
     
    # Instance methods
    # attempt to fill the order
    def fill(self, argSrc):
        print "Order:fill_"
         
        try:
            # does the warehouse has the item in stock?
            if (argSrc is not None):
                if (argSrc.hasInventory(self._orderItem)):
                    # get the item
                    locCount =    argSrc.getInventory(self._orderItem, self._orderAmount)
                 
                    # update the following property
                    self._orderFilled = locCount
                else:
                    print "Inventory item not available"
            else:
                print "Warehouse not available"
        except TypeError:
            print "Invalid warehouse"
     
    # check if the order has been filled
    def isFilled(self):
        print "Order:isFilled_"
        return (self._orderAmount == self._orderFilled)
    
class Warehouse(object):    
    # private properties
    _houseName = None
    _houseList = None
         
    # accessors
    def warehouseName(self):
        return (self._houseName)
     
    def inventory(self):
        return (self._houseList)
     
     
    # -- INVENTORY ACTIONS
    # set up the warehouse
    def setup(self, argName, argList):
        pass
     
    # check for an inventory item
    def hasInventory(self, argItem):
        pass
     
    # retrieve an inventory item
    def getInventory(self, argItem, argCount):
        pass
         
    # add an inventory item
    def addInventory(self, argItem, argCount):
        pass


 
class Test_Order(object):
    # preparing to test
    # objective: creating an order

    def test_orderCheck(self):
        """Test routine C"""
        # creating a test order
        testOrder = Order("mushrooms", 10)
        print repr(testOrder)
         
        fooSource = Mock(spec = Warehouse)
        fooSource.hasInventory.return_value = True
        fooSource.getInventory.return_value = 0
        # perform the test
        assert fooSource != None
        testOrder.fill(fooSource)
         
        # perform the checks
        assert testOrder.isFilled() == False
        assert testOrder._orderFilled == 0
         
        fooSource.hasInventory.assert_called_once_with("mushrooms")
        print fooSource.mock_calls

参考文献:1.http://www.oschina.net/translate/unit-testing-with-the-python-mock-class
                 2.https://pypi.python.org/pypi/mock

### 使用 Mock 进行 Python 接口测试 Mock 是一种用于单元测试的技术,允许开发者模拟对象的行为而不实际调用它们。在 Python 中,`unittest.mock` 提供了一个强大的工具集来实现这一目标。 #### 安装与导入 如果使用的是 Python 3.3 或更高版本,则 `unittest.mock` 已经作为标准库的一部分被包含进来[^3]。可以直接通过以下方式导入模块: ```python from unittest import mock ``` 对于更早的 Python 版本,可以通过安装外部包的方式引入该功能: ```bash pip install mock ``` 之后同样可以这样导入: ```python import mock ``` #### 基础概念 - **patch**: 替代指定的对象以便于控制其行为。 - **MagicMockMock**: 创建可配置的假象实例或类。 以下是几个常见的场景及其对应的解决方案。 #### 单一函数替换示例 当希望替代某个特定方法并定义它的返回值时,可以用如下代码片段完成操作: ```python def function_to_test(): return external_function() with mock.patch('__main__.external_function', return_value=42): result = function_to_test() assert result == 42 ``` 上述例子展示了如何利用 patch 装饰器临时改变 `external_function` 的逻辑,并验证最终的结果是否符合预期[^1]。 #### 类属性修改案例 有时需要调整类内部成员变量的内容来进行独立的功能检测。下面的例子说明了这一点: ```python class MyClass: attribute = 'original' @mock.patch.object(MyClass, 'attribute', 'new') def test_class_attribute(): assert MyClass.attribute == 'new' test_class_attribute() ``` 这里采用了装饰器的形式绑定到具体的测试函数上,从而实现了局部范围内的数据篡改[^2]。 #### 复杂依赖注入处理 针对那些拥有复杂初始化过程或者难以直接操控的目标实体来说,手动创建 mocks 并传递给待测组件是一种有效手段。 ```python fake_dependency = mock.Mock() fake_dependency.some_method.return_value = True def my_function(dependency=fake_dependency): return dependency.some_method() result = my_function(fake_dependency) assert result is True ``` 此模式特别适用于构建松耦合的设计架构,在不破坏原有结构的前提下轻松达成自动化检验的目的。 #### 总结注意事项 尽管 mock 技术极大地简化了许多棘手情况下的编码工作量,但也应谨慎对待过度抽象化可能引发的新问题。务必保持清晰简洁的思路去设计每一个环节,这样才能真正发挥出这项技术的优势所在。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值