摘要:一些常用的示例先简单定义个类,方便举例这个类里有两个成员方法,一个有参数,一个无参数。有个模块方法,返回数据库中所有指定的人员,并按排序掉整个数据库访问先得到一个的对象,再在中设置一个对象,此时不需要自己再创建
一些常用的mock示例
先简单定义个类,方便举例:
class Person: def __init__(self): self.__age = 10 def get_fullname(self, first_name, last_name): return first_name + " " + last_name def get_age(self): return self.__age @staticmethod def get_class_name(): return Person.__name__
这个类里有两个成员方法,一个有参数,一个无参数。还有一个静态方法
class PersonTest(TestCase): def test_should_get_age(self): p = Person() # 不mock时,get_age应该返回10 self.assertEqual(p.get_age(), 10) # mock掉get_age方法,让它返回20 p.get_age = Mock(return_value=20) self.assertEqual(p.get_age(), 20) def test_should_get_fullname(self): p = Person() # mock掉get_fullname,让它返回"James Harden" p.get_fullname = Mock(return_value="James Harden") self.assertEqual(p.get_fullname(), "James Harden")
上面的例子你也许已经注意到了,调用p.get_fullname时没有给任何的参数,但是依然可以工作。
如果想校验参数需要用create_autospec模块方法替代Mock类。
class PersonTest(TestCase): def test_should_get_fullname(self): p = Person() p.get_fullname = create_autospec(p.get_fullname, return_value="James Harden") # 随便给两个参数,依然会返回mock的值 self.assertEqual(p.get_fullname("1", "2"), "James Harden") # 如果参数个数不对,会报错TypeError: missing a required argument: "last_name" p.get_fullname("1")
class PersonTest(TestCase): def test_should_get_age(self): p = Person() p.get_age = Mock(side_effect=[10, 11, 12]) self.assertEqual(p.get_age(), 10) self.assertEqual(p.get_age(), 11) self.assertEqual(p.get_age(), 12)
class PersonTest(TestCase): def test_should_get_fullname(self): p = Person() values = {("James", "Harden"): "James Harden", ("Tracy", "Grady"): "Tracy Grady"} p.get_fullname = Mock(side_effect=lambda x, y: values[(x, y)]) self.assertEqual(p.get_fullname("James", "Harden"), "James Harden") self.assertEqual(p.get_fullname("Tracy", "Grady"), "Tracy Grady")
class PersonTest(TestCase): def test_should_raise_exception(self): p = Person() p.get_age = Mock(side_effect=TypeError("integer type")) # 只要调就会抛出异常 self.assertRaises(TypeError, p.get_age)
class PersonTest(TestCase): def test_should_validate_method_calling(self): p.get_fullname = Mock(return_value="James Harden") # 没调用过 p.get_fullname.assert_not_called() # Python 3.5 p.get_fullname("1", "2") # 调用过任意次数 p.get_fullname.assert_called() # Python 3.6 # 只调用过一次, 不管参数 p.get_fullname.assert_called_once() # Python 3.6 # 只调用过一次,并且符合指定的参数 p.get_fullname.assert_called_once_with("1", "2") p.get_fullname("3", "4") # 只要调用过即可,必须指定参数 p.get_fullname.assert_any_call("1", "2") # 重置mock,重置之后相当于没有调用过 p.get_fullname.reset_mock() p.get_fullname.assert_not_called() # Mock对象里除了return_value, side_effect属性外, # called表示是否调用过,call_count可以返回调用的次数 self.assertEqual(p.get_fullname.called, False) self.assertEqual(p.get_fullname.call_count, 0) p.get_fullname("1", "2") p.get_fullname("3", "4") self.assertEqual(p.get_fullname.called, True) self.assertEqual(p.get_fullname.call_count, 2)mock静态方法
静态方法和模块方法需要使用patch来mock。
class PersonTest(TestCase): # 以字符串的形式列出静态方法的路径,在测试的参数里会自动得到一个Mock对象 @patch("your.package.module.Person.get_class_name") def test_should_get_class_name(self, mock_get_class_name): mock_get_class_name.return_value = "Guy" self.assertEqual(Person.get_class_name(), "Guy")
class PersonTest(TestCase): mock_get_class_name = Mock(return_value="Guy") # 在patch中给出定义好的Mock的对象,好处是定义好的对象可以复用 @patch("your.package.module.Person.get_class_name", mock_get_class_name) def test_should_get_class_name(self): self.assertEqual(Person.get_class_name(), "Guy")
class PersonTest(TestCase): mock_get_class_name = Mock(return_value="Guy") # 使用patch.object来mock,好处是Person类不是以字符串形式给出的 @patch.object(Person, "get_class_name", mock_get_class_name) def test_should_get_class_name(self, ): self.assertEqual(Person.get_class_name(), "Guy")
class PersonTest(TestCase): # 作用域之外,依然返回真实值 def test_should_get_class_name(self, ): mock_get_class_name = Mock(return_value="Guy") with patch("your.package.module.Person.get_class_name", mock_get_class_name): self.assertEqual(Person.get_class_name(), "Guy") self.assertEqual(Person.get_class_name(), "Person")mock链式调用
在django里,我们经常需要mock数据库,而访问数据库时经常是链式调用,看个例子。
def get_person(name): return Person.objects.filter(name=name).order_by("age")
有个模块方法,返回数据库中所有指定name的人员,并按age排序
mock掉整个数据库访问
@patch("your.package.module.Person.objects.filter") def test_should_get_person(self, mock_filter): # 先得到一个filter的Mock对象,再在return_value中设置一个Mock对象,此时不需要自己再创建 mock_filter.return_value.order_by.return_value = None self.assertIsNone(get_person())
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/45535.html
摘要:每个测试方法的名称以单词开头,单元测试是如何识别它们是测试的。它还意味着知道测试文件中有多少单元测试,而不是简单地知道有多少表达式您可能已经注意到将每个行作为单独的测试计数。 showImg(https://segmentfault.com/img/remote/1460000019140153); 来源 | 愿码(ChainDesk.CN)内容编辑 愿码Slogan | 连接每个程...
摘要:准确的说,是中一个用于支持单元测试的库,它的主要功能是使用对象替代掉指定的对象,以达到模拟对象的行为。下面我们使用对象在单元测试中分别测试访问正常和访问不正常的情况。 Mock是什么 Mock这个词在英语中有模拟的这个意思,因此我们可以猜测出这个库的主要功能是模拟一些东西。准确的说,Mock是Python中一个用于支持单元测试的库,它的主要功能是使用mock对象替代掉指定的Python...
摘要:接下来我们将介绍如何对对象的方法进行模拟测试。选项创建模拟测试接口我们可以在的构造函数中提供一个模拟测试实例,而不是模拟创建具体的模拟测试方法。 如何不靠耐心测试 通常,我们编写的软件会直接与那些我们称之为肮脏的服务交互。通俗地说,服务对我们的应用来说是至关重要的,它们之间的交互是我们设计好的,但这会带来我们不希望的副作用——就是那些在我们自己测试的时候不希望的功能。 比如,可能我们...
摘要:也就是说,如果不需要,两者使用起来并没有什么分别。来看个例子,先定义个类,里面只有一个成员方法,返回倍的数值使用类来掉这个成员方法使用类来两者没有任何区别,都成功了了成员方法。再看下两者的区别因为使用类时,默认不会创建这个的,所以报错。 Python的unittest.mock模块中提供了两个主要的mock类,分别是Mock和MagicMock. 先看一下官方文档的定义: MagicM...
阅读 2312·2021-11-17 09:33
阅读 842·2021-10-13 09:40
阅读 572·2019-08-30 15:54
阅读 777·2019-08-29 15:38
阅读 2416·2019-08-28 18:15
阅读 2474·2019-08-26 13:38
阅读 1840·2019-08-26 13:36
阅读 2128·2019-08-26 11:36