您的位置:首页 > 编程语言 > Python开发

Python中的模块学习之mock模块

2017-08-10 23:31 316 查看
学习Python也有一段时间了,然而对Python中的单元测试模块这些并不是很懂,刚好,今天有点时间,就将mock模块进行学习并整理,下边进行分享:

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



为什么要使用mock?

场景模拟1:比如有A和B两个模块,A模块中有调用到B模块的方法,但是很不幸,B模块中被A模块调用的方法由于一定的原因需要被修改,然而我们又不想让影响A模块的功能测试,所以就用到了单元测试模块unittest中的mock模块;mock模块就是模拟出一个假的B模块;

场景模拟2:有时需要为单元测试的初始设置准备一些其他的资源,但是这些资源又不太经常使用或者是使用起来比较笨拙,此时我们就可以定义一个mock对象来模拟一个需要使用的资源;mock对象用于代替测试的准备资源;

下边先来看一下mock对象都有哪些属性?知道这些属性,后续使用mock才会得心应手;



网上看到有人将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参数:



从上述的举例中可以看出,name标识了唯一的一个mock(print的时候,后边会显示ID)。

2.return_value参数:

a.指定的是某个值:



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

b.指定的是某个类的对象:



3.side_effect参数:

a.指定的参数的值是异常



从上边的例子可以看出,当side_effecr被设置的时候,return_value就被屏蔽了,不起作用了,上边side_effect被设置的是一个异常。

b.指定的参数的值是一个list或者tuple:



插入:到这里居然想起了python中的生成器函数,yield的用法有点像return,返回的是一个生成器函数,当调用这个函数的时候,写在函数中的代码并没有真正执行,他只是返回了一个生成器。

看下边的例子:通过下边的函数创建出了一个生成器之后,每次执行next操作,都会返回一个值,当返回完的时候,就会抛出异常。



4.spec参数:

a.指定的是属性组成的list



b.指定的是一个类属性:



正如文章开头所说,spec设置的是mock对象的属性,所以,这下,mock就有了3个属性了。

二、mock的断言:

1.assert_called_with(*argSeq, **argKW):检查mock方法是否获得了正确的参数;当至少有一个参数有错误的值或者类型时,当参数的个数出错时,当参数的顺序不正确时,这个断言就会发生错误。



参数个数错误的举例,这里就不给出了~~上边,mockFoo对象调用了fun2函数多次,但是有些时候,我们只是希望mock对象调用某个方法一次,所以,就有了下边的一个断言:

2.assert_called_once_with(*argSeq, **argKW)这个断言,当某个方法被多次调用的时候,它就会报错,看下边的例子:

注明:下边这个例子是接着上边的例子的,看上边,上边的例子中我们已经调用了fun1一次了,所以,下边的例子提示断言错误,并且还有次数显示呢~



3.assert_any_call()用于检查测试的mock对象在测试例程中是否调用了方法,和前边的两个断言不一样,前边的两个只是检查最近一次的调用;看下边的例子(mock的构造仍和上边的例子一样);



4.assert_has_calls()检查是否按照正确的顺序和正确的参数进行调用的;所以,我们需要给出一个方法的调用顺序,assert的时候按照这个顺序进行检查。



注明:第一次assert失败是因为参数给错了哎。

还有,仔细看你会看到,fooCall中的每个元素前边都有call来修饰,这个就是表明,call后边的是一个方法,不加call是不可以的,解释器是不知道fun1是一个方法的,为了使用call这个关键字,我们就需要引入这个模块:from mock import Mock,call。

三、mock的管理方法:

1.attach_mock():将一个mock对象添加到另一个mock对象中;



上述例子中,我们是将mockFoo2添加到mockFoo1中,并重新命名为mock_att。或许,看到这里,你会很好奇,为什么mockFoo1._value1取到的不是100,而是一些id信息呢?因为,哈哈哈,spec只是设置的是mock对象的属性,也就是说mock对象有这些属性,但是属性的值呢~~就说不定了~

2.configure_mock():更改mock对象的return_value值。

举例说明:



疑问:

为什么mockFoo.fun1不会显示出来fun1函数的输出或者是fun1的return_value值呢???

人为原因:sooSpec字典的写法出现错误,应该这么写:



(value值也必须带上引号,但是最后那个异常就不需要了),这样子纠正之后,print mockFoo.fun1()显示的结果就是100.

3.mock_add_spec(aSpec, spec_set = False):这个函数就是给mock对象添加一个新的属性(mock对象原来的属性就会被擦除),第二个参数是指属性是可读可写,默认是只读,如果想让其拥有写权限,可以将其设置为true.



4.reset_mock():将mock对象恢复到测试之前的状态,这里也就是避免了重新构造mock对象带来的开销。这里就不给出举例~

四、mock的统计:

1.called:跟踪mock对象所做的任意调用的访问器;



2.call_count:mock对象被工厂调用的次数:



此例子接着上述例子;

3.call_args:获取工厂调用时的参数(最近使用的参数):



4.call_args_list:获取工厂调用的的所有参数,是个列表;

5.method_calls:测试一个mock对象都调用了哪些方法,结果是一个list。



6.mock_calls:显示工厂调用和方法调用,下图所示:



关于mock模块的分享,就先到这里了~后续会继续更新其他的模块的学习~对了,如果上述分享内容有疑问,请记得留言呦~感谢你~

愿我所爱之人都能实现自己的梦想~愿大家都有美好的前程~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息