python mock (一)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/I_itaiit/article/details/82532148

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参数。

    扫描二维码关注公众号,回复: 3086697 查看本文章
  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

猜你喜欢

转载自blog.csdn.net/I_itaiit/article/details/82532148