python mock

mock测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法。

参考:

  • 为什么使用mock

  • Mock Class:

    class unittest.mock.Mock(spec=None, side_effect=None, return_value=DEFAULT, wraps=None, name=None, spec_set=None, unsafe=False, **kwargs)

    MagicMock是Mock的子类。


  1. 当mock被调用之后,它的called属性将会被设置为True,我们也可以调用其assert_called_with()或者assert_called_once_with()来检查是否正确的调用。

    from mock import MagicMock
    
    class ProductionClass(object):
            def closer(self, something):
                    something.close()
    
    real = ProductionClass()
    mock = MagicMock()
    real.closer(mock)
    print mock.close.called
    mock.close.assert_called_once_with()
    结果:
    	True	
    

    在大多数情况下,Mock和MagicMock是可以交换使用的,MagicMock是Mock的子类。

  2. return_value的使用

    文件learnmock03.py

    class ProductionClass(object):
            def __init__(self):
                    pass
            def method(self):
                    return "the result"
    

    文件learnmock04.py

    from mock import MagicMock
    from mock import patch
    from learnmock03 import ProductionClass
    
    def some_function():
            instance = ProductionClass()
            return instance.method()
    
    with patch('learnmock03.ProductionClass') as mock:
            # 使用mock调用
            instance = mock.return_value
            instance.method.return_value = 'the result'
            # 创建对象调用
            result = some_function()
            assert result == 'the result'
    
  3. 在创建Mock的时候可以设置name参数。

  4. 设置返回值和属性

    需要导入from mock import Mock

    • 设置返回值

      >>> mock = Mock()
      >>> mock.return_value = 3
      >>> mock()
      返回:
      3
      
      >>> mock = Mock()
      >>> mock.method.return_value = 3
      >>> mock.method()
      返回:
      3
      
      >>> mock = Mock(return_value=3)
      >>> mock()
      返回:
      3
      
    • 设置属性

      >>> mock = Mock()
      >>> mock.x = 3
      >>> mock.x
      返回:
      3
      
  5. Side effect

    • 将side_effect的值设置为None来清除side_effect

    • side_effect是一个方法,当mock被调用的时候,side_effect也会被调用。side_effect可以被赋值为一个函数或者是异常,在调用mock时,side_effect也会被执行:

      from mock import MagicMock
      
      class Class:
              def method(self):
                      pass
      
      def method():
              print "print side_effect"
      
      mock = MagicMock(side_effect = method)
      
      mock()
      
      mock.assert_called_once__with()
      

      将会打印:print side_effect

      若将side_effect设置为某个异常,例如side_effect=Exception("Boom!"),则在调用mock时将会抛出异常。

  6. Decorators

    • patch

      使用一个简单的string,格式为:package.module.Class.attribute

      >>> @patch('__main__.SomeClass')
      ... def function(normal_argument, mock_class):
      ...     print(mock_class is SomeClass)
      

      @patch所产生的对象将会传给所修饰的方法,并作为方法的最后一个参数,在上面的代码中则是mock_class;

      注意如果patch的类在当前文件中定义,@patch的字符串参数要使用__main__修饰;

      看下面的情况:

      from mock import patch
      
      class Class01:
              def method(self):
                      pass
      class Class02:
              def method(self):
                      pass
      @patch("__main__.Class01")
      @patch("__main__.Class02")
      def test(mockClass02, mockClass01):
              assert mockClass02.return_value is Class02()
              assert mockClass01.return_value is Class01()
      
      test()    
      

      当有多个@patch修饰同一个方法时,遵循bottom---->up的顺序,为方法传参。

    • patch.object

      使用一个对象+该对象上的一个属性的名字[+]属性的值

      1. 类属性:
      from mock import patch
      
      class SomeClass:
              attribute = "originalvalue"
              
      @patch.object(SomeClass, 'attribute', 'sentinel.attribute')
      def test():
              print SomeClass.attribute
              assert SomeClass.attribute == 'sentinel.attribute'
      test()
      结果:
      sentinel.attribute
      
      1. 实例属性:
      from mock import patch
      
      class SomeClass:
              def __init__(self, attr):
                      self.attr = attr
      
      original = SomeClass("attr_value")
      print original
      @patch.object(original, 'attr', 'sentinel.attribute')
      
      def test():
              print original.attr
              assert original.attr == 'sentinel.attribute_2'
      test()
      
    • patch.dict

  7. 当使用patch创建mock时,将会返回该mock的引用,使用as接收

    with patch.object(ProductionClass, 'method') as mock_method:
    	...
    
  8. 获得instance的两种方式

    >>> class Class:
    ...     def method(self):
    ...         pass
    ...
    >>> with patch('__main__.Class') as MockClass:
    ...     instance = MockClass.return_value
    ...     instance.method.return_value = 'foo'
    ...     assert Class() is instance
    ...     assert Class().method() == 'foo'
    
    >>> Original = Class
    >>> patcher = patch('__main__.Class', spec=True)
    >>> MockClass = patcher.start()
    >>> instance = MockClass()
    >>> assert isinstance(instance, Original)
    >>> patcher.stop()
    

    mock() == mock.return_value

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值