猴子补丁:函数或者对象已经定义好列,再去改变他们的行为

 

先来看一下本文的整体框架:
python之mock

为什么要使用mock?
场景模拟1:比如有A和B两个模块,A模块中有调用到B模块的方法,但是很不幸,B模块中被A模块调用的方法由于一定的原因需要被修改,然而我们又不想让影响A模块的功能测试,所以就用到了单元测试模块unittest中的mock模块;mock模块就是模拟出一个假的B模块;
场景模拟2:有时需要为单元测试的初始设置准备一些其他的资源,但是这些资源又不太经常使用或者是使用起来比较笨拙,此时我们就可以定义一个mock对象来模拟一个需要使用的资源;mock对象用于代替测试的准备资源;
下边先来看一下mock对象都有哪些属性?知道这些属性,后续使用mock才会得心应手;
python之mock
网上看到有人将mock的方法进行了分类:
python之mock


一、构造器

init是mock对象的构造器,name是mock对象的唯一标识;spec设置的是mock对象的属性,可以是property或者方法,也可以是其他的列表字符串或者其他的python类;return_value设置的是,当这个mock对象被调用的时候,显示出的结果就是return_value的值;side_effect是和return_value是相反的,覆盖了return_value,也就是说当这个mock对象被调用的时候,返回的是side_effect的值,而不是return_value。
举例说明:
1.name参数:
python之mock
从上述的举例中可以看出,name标识了唯一的一个mock(print的时候,后边会显示ID)。
2.return_value参数:
a.指定的是某个值:

python之mock
从上边的例子可以看出,当我们调用mock对象的时候,显示的就是return_value的值(也就是说mockObj是带有一定的功能的);
b.指定的是某个类的对象:

python之mock
3.side_effect参数:
a.指定的参数的值是异常
python之mock
从上边的例子可以看出,当side_effecr被设置的时候,return_value就被屏蔽了,不起作用了,上边side_effect被设置的是一个异常。
b.指定的参数的值是一个list或者tuple:
python之mock
插入:到这里居然想起了python中的生成器函数,yield的用法有点像return,返回的是一个生成器函数,当调用这个函数的时候,写在函数中的代码并没有真正执行,他只是返回了一个生成器。
看下边的例子:通过下边的函数创建出了一个生成器之后,每次执行next操作,都会返回一个值,当返回完的时候,就会抛出异常。
python之mock
4.spec参数:
a.指定的是属性组成的list
python之mock
b.指定的是一个类属性:
python之mock
正如文章开头所说,spec设置的是mock对象的属性,所以,这下,mock就有了3个属性了。


二、mock的断言:

1.assert_called_with(*argSeq, **argKW):检查mock方法是否获得了正确的参数;当至少有一个参数有错误的值或者类型时,当参数的个数出错时,当参数的顺序不正确时,这个断言就会发生错误。
python之mock
参数个数错误的举例,这里就不给出了~~上边,mockFoo对象调用了fun2函数多次,但是有些时候,我们只是希望mock对象调用某个方法一次,所以,就有了下边的一个断言:
2.assert_called_once_with(*argSeq, **argKW)这个断言,当某个方法被多次调用的时候,它就会报错,看下边的例子:
注明:下边这个例子是接着上边的例子的,看上边,上边的例子中我们已经调用了fun1一次了,所以,下边的例子提示断言错误,并且还有次数显示呢~
python之mock
3.assert_any_call()用于检查测试的mock对象在测试例程中是否调用了方法,和前边的两个断言不一样,前边的两个只是检查最近一次的调用;看下边的例子(mock的构造仍和上边的例子一样);
python之mock
4.assert_has_calls()检查是否按照正确的顺序和正确的参数进行调用的;所以,我们需要给出一个方法的调用顺序,assert的时候按照这个顺序进行检查。
python之mock
注明:第一次assert失败是因为参数给错了哎。
还有,仔细看你会看到,fooCall中的每个元素前边都有call来修饰,这个就是表明,call后边的是一个方法,不加call是不可以的,解释器是不知道fun1是一个方法的,为了使用call这个关键字,我们就需要引入这个模块:from mock import Mock,call。


三、mock的管理方法:

1.attach_mock():将一个mock对象添加到另一个mock对象中;
python之mock
上述例子中,我们是将mockFoo2添加到mockFoo1中,并重新命名为mock_att。或许,看到这里,你会很好奇,为什么mockFoo1._value1取到的不是100,而是一些id信息呢?因为,哈哈哈,spec只是设置的是mock对象的属性,也就是说mock对象有这些属性,但是属性的值呢~~就说不定了~
2.configure_mock():更改mock对象的return_value值。
举例说明:
python之mock
疑问:
为什么mockFoo.fun1不会显示出来fun1函数的输出或者是fun1的return_value值呢???
人为原因:sooSpec字典的写法出现错误,应该这么写:
python之mock
(value值也必须带上引号,但是最后那个异常就不需要了),这样子纠正之后,print mockFoo.fun1()显示的结果就是100.
3.mock_add_spec(aSpec, spec_set = False):这个函数就是给mock对象添加一个新的属性(mock对象原来的属性就会被擦除),第二个参数是指属性是可读可写,默认是只读,如果想让其拥有写权限,可以将其设置为true.
python之mock
4.reset_mock():将mock对象恢复到测试之前的状态,这里也就是避免了重新构造mock对象带来的开销。这里就不给出举例~


四、mock的统计:

1.called:跟踪mock对象所做的任意调用的访问器;
python之mock
2.call_count:mock对象被工厂调用的次数:
python之mock
此例子接着上述例子;
3.call_args:获取工厂调用时的参数(最近使用的参数):
python之mock
4.call_args_list:获取工厂调用的的所有参数,是个列表;
5.method_calls:测试一个mock对象都调用了哪些方法,结果是一个list。
python之mock
6.mock_calls:显示工厂调用和方法调用,下图所示:
python之mock

--------------------- 本文来自 peiyao456 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/peiyao456/article/details/77075173?utm_source=copy

分类:

技术点:

相关文章: