zoukankan      html  css  js  c++  java
  • unittest mock基本使用

    mock介绍

    mock允许用模拟对象替换系统中真实对象,并对它们已使用的方式进行断言。

    在进行单元测试的时候,会遇到以下问题:
    •接口的依赖;
    •外部接口调用;
    •测试环境非常复杂。
    且单元测试应该只针对当前单元进行测试, 所有的内部或外部的依赖应该是稳定的, 已经在别处进行测试过的.使用mock 就可以对外部依赖组件实现进行模拟并且替换掉, 从而使得单元测试将焦点只放在当前的单元功能。

    以下一个简单的示例:

    调用mock并指定 reutrn_value 创建一个mock对象,然后mock 掉 say_hello 函数对象后,这个方法的一切动作,比如 print 就变得没有意义了,因为最后这个方法只会做一件事就是返回我们为其指定的返回值。

    from unittest.mock import Mock
    
    
    def say_hello(word):
        print(f"Hello {word}")
    
    say_hello("China")
    mock=Mock(return_value="PYTHON OH YEAH")
    say_hello=mock
    say_hello("China")

    mock模块的基本使用

    return_vaule 

    mock 对象的 return_vaule 的作用:它将忽略 mock 对象的行为,指定其返回值。

    modular.py

    class Count():
    
        def add(self):
            pass

    mock_demo01.py

    from unittest import mock
    import unittest
    
    from modular import Count
    
    # test Count class
    class TestCount(unittest.TestCase):
    
        def test_add(self):
            count = Count()
            count.add = mock.Mock(return_value=13)
            result = count.add(8,5)
            self.assertEqual(result,13)
    
    if __name__ == '__main__':
        unittest.main()

    假设Count计算类没有实现,原本add() 方法要实现两数相加。但这个功能还没有完成。这时就可以借助mock对其进行测试。  

    count = Count()

    首先,调用被测试类Count() 。

    count.add = mock.Mock(return_value=7)

    通过Mock类模拟被调用的方法add()方法,return_value 定义add()方法的返回值。

    result = count.add(2,5)

    接下来,相当于在正常的调用add()方法,传两个参数2和5,然后会得到相加的结果7。然后,7的结果是我们在上一步就预先设定好的。

    self.assertEqual(result,7)

    最后,通过assertEqual()方法断言,返回的结果是否是预期的结果7。

    side_effect

    mock 对象的side_effect 的作用:通过side_effect指定mock对象的副作用,这个副作用就是当你调用这个mock对象时会调用的函数,也可以选择抛出一个异常,来对程序的错误状态进行测试。

    from unittest.mock import Mock
    
    
    def say_hello(word):
        print(f"Hello {word}")
    
    
    mock=Mock()
    #指定为函数
    mock.side_effect  = say_hello
    mock('china')
    
    #指定为异常
    mock.side_effect  = KeyError('This is b') #Exception("Raise Exception")
    mock()

     另外也可以通过为side_effect指定一个列表,这样在每次调用时会依次返回,如下:

    from unittest.mock import Mock
    
    
    mock=Mock(side_effect = [1, 2, 3])
    print(mock())
    print(mock())
    print(mock())

    patch装饰器

      它是一个装饰器,需要把你想模拟的函数写在里面,然后在后面的单元测试案例中为它赋一个具体实例,再用 return_value 来指定模拟的这个函数希望返回的结果就可以了,后面就是正常单元测试代码。

    @mock.pathc.object(类名,“类中函数名”)

    from unittest import mock
    import unittest
    
    class Count():
    
        def add(self):
            pass
    
    
    # test Count class
    class TestCount(unittest.TestCase):
    
        @mock.patch.object(Count, "add")
        def test_add(self, mock_add):
            mock_add. return_value = 13
            result = mock_add()
            self.assertEqual(result,13)
    
    if __name__ == '__main__':
        unittest.main()

    @mock.pathc(模块名,“函数名”)

    linux_tool.py

    import re
     
    def send_shell_cmd():
        return "Response from send_shell_cmd function"
     
    def check_cmd_response():
        response = send_shell_cmd()
        print("response: {}".format(response))
        return re.search(r"mock_send_shell_cmd", response)

    测试代码:

    from unittest import TestCase, mock
    import linux_tool
     
    class TestLinuxTool(TestCase):
        def setUp(self):
            pass
     
        def tearDown(self):
            pass
     
        @mock.patch("linux_tool.send_shell_cmd")
        def test_check_cmd_response(self, mock_send_shell_cmd):
            mock_send_shell_cmd.return_value = "Response from emulated mock_send_shell_cmd function"
     
            status = linux_tool.check_cmd_response()
            print("check result: %s" % status)
            self.assertTrue(status)

    如果 patch 多个外部函数,那么调用遵循自下而上的规则,比如:

    @mock.patch("function_C")
    @mock.patch("function_B")
    @mock.patch("function_A")
    def test_check_cmd_response(self, mock_function_A, mock_function_B, mock_function_C):
        mock_function_A.return_value = "Function A return"
        mock_function_B.return_value = "Function B return"
        mock_function_C.return_value = "Function C return"
     
        self.assertTrue(re.search("A", mock_function_A()))
        self.assertTrue(re.search("B", mock_function_B()))
        self.assertTrue(re.search("C", mock_function_C()))

    一个示例

    Count类中add_and_multiply依赖multiply,由于multiply并没有实现,这时候可以使用mock替换multiply:

    from unittest import mock
    import unittest
    
    class Count():
    
        def add_and_multiply(self,x, y):
            addition = x + y
            multiple = self.multiply(x, y)
            return (addition, multiple)
    
        def multiply(self,x, y):
            pass
    
    
    # test Count class
    class TestCount(unittest.TestCase):
    
        @mock.patch.object(Count, "multiply")
        def test_add(self, mock_multiply):
            mock_multiply. return_value = 40
            count = Count()
            addition,multiple = count.add_and_multiply(5,8)
            self.assertEqual(addition,13)
            self.assertEqual(multiple, 40)
    
    if __name__ == '__main__':
        unittest.main()
  • 相关阅读:
    [HDU1087]Super Jumping! Jumping! Jumping!<dp>
    [codeforces]Page Numbers <模拟>
    [POJ1190]生日蛋糕<DFS>
    [HDU1029]Ignatius and the Princess IV<桶 水题>
    矩阵优化
    康复式训练
    bzoj1036 [ZJOI2008]树的统计Count
    luogu3761 [TJOI2017]城市
    bzoj2282 [SDOI2011]消防
    NOI2014
  • 原文地址:https://www.cnblogs.com/-wenli/p/14197318.html
Copyright © 2011-2022 走看看