1、重置方法

reset_mock:将mock对象恢复到测试之前的状态(相当于没有调用过)。

1、创建Demo.py文件(创建被测试类:People类)。

脚本代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
被测试类
"""
# People类里有两个成员方法(一个有参数,一个无参数)、一个静态方法
class People:

    def __init__(self):
        self.__age = 20

    def name(self,firstName,lastName):
        return firstName + ' ' + lastName

    def age(self):
        return self.__age

    @staticmethod
    def class_name():
        return People.__name__

 

2、创建MockTest_reset_mock.py文件(创建PeopleTest测试类)。

脚本代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
重置方法
"""
from method.Demo import People
from unittest import mock
import unittest

class PeopleTest(unittest.TestCase):

    def test_name(self):
        # 调用被测试类People()
        p = People()
        p.name = mock.Mock(return_value='Hello Mock')
        p.name('a', 'b')
        p.name.reset_mock()
        p.name.assert_not_called()

if __name__ == '__main__':
    unittest.main(verbosity=2)

 

3、执行MockTest_reset_mock.py文件,运行结果:

调用p.name()方法,之后用reset_mock重置mock,最后用assert_not_called验证p.name()方法从未被调用过,执行成功。

图片


 

2、create_autospec

 

 

create_autospec:校验参数个数,再返回固定值;create_autospec方法替代Mock方法。

1、创建Demo.py文件(创建被测试类:People类)。

脚本代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
被测试类
"""
# People类里有两个成员方法(一个有参数,一个无参数)、一个静态方法
class People:

    def __init__(self):
        self.__age = 20

    def name(self,firstName,lastName):
        return firstName + ' ' + lastName

    def age(self):
        return self.__age

    @staticmethod
    def class_name():
        return People.__name__

 

2、创建MockTest_create_autospec.py文件(创建PeopleTest测试类)。

脚本代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
create_autospec(校验参数个数,再返回固定值)
"""
from method.Demo import People
from unittest import mock
import unittest

class PeopleTest(unittest.TestCase):

    def test_name(self):
        # 调用被测试类People()
        p = People()
        p.name = mock.create_autospec(p.name, return_value='Hello Mock')
        print(p.name('a','b'))
        self.assertEqual(p.name('a','b'), 'Hello Mock')
        print(p.name('a'))

if __name__ == '__main__':
    unittest.main(verbosity=2)

 

3、执行MockTest_create_autospec.py文件,运行结果:

(1)如果想校验参数需要用create_autospec方法替代Mock方法。

(2)随便传两个参数('a','b'),依然会返回mock的值(Hello Mock)。

(3)如果参数个数不对(传一个参数'a'),则会报错(例如TypeError: missing a required argument: 'lastName')。

图片


 

3、装饰器/上下文管理器

 

 

mock库提供了patch函数来简化mock对象对原对象的替换。patch可以作为装饰器或者上下文管理器使用,这意味着在装饰的函数和上下文管理器中,对应的类会被替换为mock对象。

创建Demo.py文件(创建被测试类:People类)。

脚本代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
被测试类
"""
# People类里有两个成员方法(一个有参数,一个无参数)、一个静态方法
class People:

    def __init__(self):
        self.__age = 20

    def name(self,firstName,lastName):
        return firstName + ' ' + lastName

    def age(self):
        return self.__age

    @staticmethod
    def class_name():
        return People.__name__

 

3.1、@patch

3.1.1、在测试方法参数中得到Mock对象

1、创建MockTest_patch1.py文件(创建PeopleTest测试类)。

脚本代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
装饰器/上下文管理器:@patch(在测试方法参数中得到Mock对象)
"""
from method.Demo import People
from unittest.mock import patch
import unittest

class PeopleTest(unittest.TestCase):

    @patch('method.Demo.People.class_name')
    def test_class_name(self, mock_class_name):
        mock_class_name.return_value = 'Hello Mock'
        print(People.class_name())

if __name__ == '__main__':
    unittest.main(verbosity=2)

 

2、执行MockTest_patch1.py文件,运行结果:

(1)@patch以字符串的形式列出静态方法的路径,在测试方法(test_class_name)的参数里会自动得到一个Mock对象(mock_class_name)。

(2)设置class_name静态方法返回值为Hello Mock。

(3)调用People.class_name()静态方法,返回预设值Hello Mock。

图片

 

3.1.2、在patch中设置Mock对象

1、创建MockTest_patch2.py文件(创建PeopleTest测试类)。

脚本代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
装饰器/上下文管理器:@patch(在patch中设置Mock对象)
"""
from method.Demo import People
from unittest import mock
from unittest.mock import patch
import unittest

class PeopleTest(unittest.TestCase):

    mock_class_name = mock.Mock(return_value='Hello Mock')
    @patch('method.Demo.People.class_name', mock_class_name)
    def test_class_name(self):
        print(People.class_name())

if __name__ == '__main__':
    unittest.main(verbosity=2)

 

2、执行MockTest_patch2.py文件,运行结果:

(1)定义Mock对象,设置返回值为Hello Mock。

(2)在@patch中给出定义好的Mock的对象,好处是定义好的对象可以复用。

(3)调用People.class_name()静态方法,返回预设值Hello Mock。

图片

 

3.2、@patch.object

1、创建MockTest_patch_object.py文件(创建PeopleTest测试类)。

脚本代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
装饰器/上下文管理器:@patch.object
"""
from method.Demo import People
from unittest import mock
from unittest.mock import patch
import unittest

class PeopleTest(unittest.TestCase):

    mock_class_name = mock.Mock(return_value='Hello Mock')
    @patch.object(People, 'class_name', mock_class_name)
    def test_class_name(self):
        print(People.class_name())

if __name__ == '__main__':
    unittest.main(verbosity=2)

 

2、执行MockTest_patch_object.py文件,运行结果:

(1)定义Mock对象,设置返回值为Hello Mock。

(2)使用@patch.object来mock,好处是People类不是以字符串形式给出的。

(3)调用People.class_name()静态方法,返回预设值Hello Mock。

图片

 

3.3、with

1、创建MockTest_patch_with.py文件(创建PeopleTest测试类)。

脚本代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
装饰器/上下文管理器:使用with控制作用域
"""
from method.Demo import People
from unittest import mock
from unittest.mock import patch
import unittest

class PeopleTest(unittest.TestCase):

    def test_class_name(self):
        mock_class_name = mock.Mock(return_value='Hello Mock')
        with patch('method.Demo.People.class_name', mock_class_name):
            print(People.class_name())
        print(People.class_name())

if __name__ == '__main__':
    unittest.main(verbosity=2)

 

2、执行MockTest_patch_with.py文件,运行结果:

(1)定义Mock对象,设置返回值为Hello Mock。

(2)使用with控制作用域,调用第一个People.class_name()静态方法(作用域内),返回预设值Hello Mock;调用第二个People.class_name()静态方法(作用域外),返回真实值People。

图片

 

 

4、依赖测试

 

 

场景:我们要测试A模块,A模块依赖于B模块的调用。但是由于B模块的改变,导致了A模块返回结果的改变,以至于A模块测试用例失败。对于A模块,以及A模块的用例来说,并没有变化,不应失败才对。这个时候就要利用mock模拟掉影响A模块的部分(B模块),使A模块顺利执行测试用例并且成功。

一、创建Demo.py文件。

创建被测试函数(moduleA、moduleB)

脚本代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
依赖测试:被测试函数
"""
def moduleA(x, y):
    valueA = x + y
    valueB = moduleB(x, y)
    return (valueA,valueB)

def moduleB(x, y):
    return x - y + 5

 

二、创建MockTest.py文件。

创建TestDemo测试类。

1、不使用mock

1.1、脚本代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
依赖测试:测试类
"""
import unittest
from dependent import Demo

class TestDemo(unittest.TestCase):

    def test_moduleA(self):
        x = 5
        y = 3
        valueA, valueB = Demo.moduleA(x, y)
        self.assertEqual(8, valueA)
        self.assertEqual(7, valueB)

if __name__ == '__main__':
    unittest.main(verbosity=2)

 

1.2、执行MockTest.py文件,运行结果:

(1)valueA返回8(5+3)。

(2)valueB返回7(5-3+5)。

图片

 

2、使用mock

2.1、脚本代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
依赖测试:测试类
"""
import unittest
from dependent import Demo
from unittest.mock import patch

class TestDemo(unittest.TestCase):             

    @patch('dependent.Demo.moduleB')
    def test_moduleA_mock(self, mock_moduleB):
        x = 5
        y = 3
        mock_moduleB.return_value = 10
        valueA, valueB = Demo.moduleA(x, y)
        mock_moduleB.assert_called_once_with(5, 3)
        self.assertEqual(8, valueA)
        self.assertEqual(10, valueB)

if __name__ == '__main__':
    unittest.main(verbosity=2)

 

2.2、执行MockTest.py文件,运行结果:

(1)在定义测试用例中,将Demo的moduleB()函数(对象)重命名为mock_moduleB对象。

(2)设置mock_moduleB(moduleB()函数)返回值为10。

(3)调用Demo.moduleA()函数,并得到valueA, valueB返回值。

(4)验证mock_moduleB被调用了一次,并且该调用使用了指定的参数(5, 3)。

(5)验证valueA,返回8(5+3)。

(6)验证valueB,返回10(moduleB()函数被设置返回值为10)。

图片

如果您觉得文章还不错,请 点赞、分享、在看、收藏 一下,因为这将是我持续输出更多优质文章的最强动力!

如果文章对你有帮助,麻烦伸出可爱的小手点个赞,感谢您的支持,你的点赞是我持续更新的动力。在这里推荐一个我自己创建的软件测试交流群,QQ:642830685,群中机会不定期的分享软件测试资源和面试题,以及行业资讯,大家可以在群中积极交流问题呀。

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐