setUp的python中正确使用模拟

setUp的python中正确使用模拟

本文介绍了如何在带有unittest setUp的python中正确使用模拟的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在尝试学习TDD时,尝试学习单元测试并在python中使用模拟.慢慢掌握它,但不确定我是否正确执行此操作.预先警告:由于供应商API是预编译的2.4 pyc文件,因此我使用python 2.4卡住了,所以我使用的是模拟0.8.0和unittest(不是unittest2)

In my attempt to learn TDD, trying to learn unit testing and using mock with python. Slowly getting the hang of it, but unsure if I'm doing this correctly. Forewarned: I'm stucking using python 2.4 because the vendor API's come as pre-compiled 2.4 pyc files, so I'm using mock 0.8.0 and unittest ( not unittest2 )

给出"mymodule.py"中的示例代码

Given this example code in 'mymodule.py'

import ldap

class MyCustomException(Exception):
    pass

class MyClass:
    def __init__(self, server, user, passwd):
        self.ldap = ldap.initialize(server)
        self.user = user
        self.passwd = passwd

    def connect(self):
        try:
            self.ldap.simple_bind_s(self.user, self.passwd)
        except ldap.INVALID_CREDENTIALS:
            # do some stuff
            raise MyCustomException

现在在我的测试用例文件'test_myclass.py'中,我想模拟ldap对象. ldap.initialize返回ldap.ldapobject.SimpleLDAPObject,因此我认为这是我必须模拟的方法.

Now in my test case file 'test_myclass.py', I want to mock the ldap object out. ldap.initialize returns the ldap.ldapobject.SimpleLDAPObject, so I figured that'd be the method I'd have to mock out.

import unittest
from ldap import INVALID_CREDENTIALS
from mock import patch, MagicMock
from mymodule import MyClass

class LDAPConnTests(unittest.TestCase):
    @patch('ldap.initialize')
    def setUp(self, mock_obj):
        self.ldapserver = MyClass('myserver','myuser','mypass')
        self.mocked_inst = mock_obj.return_value

    def testRaisesMyCustomException(self):
        self.mocked_inst.simple_bind_s = MagicMock()
        # set our side effect to the ldap exception to raise
        self.mocked_inst.simple_bind_s.side_effect = INVALID_CREDENTIALS
        self.assertRaises(mymodule.MyCustomException, self.ldapserver.connect)

    def testMyNextTestCase(self):
        # blah blah

使我遇到几个问题:

  1. 看起来不错吗? :)
  2. 这是尝试模拟在我正在测试的类中实例化的对象的正确方法吗?
  3. 可以在setUp上调用@patch装饰器,还是会引起怪异的副作用?
  4. 是否有必要进行模拟以引发ldap.INVALID_CREDENTIALS异常,而不必将该异常导入我的测试用例文件中?
  5. 我应该改用patch.object(),如果可以,怎么办?

谢谢.

推荐答案

您可以将patch()用作类装饰器,而不仅仅是用作函数装饰器.然后,您可以像以前一样传递模拟函数:

You can use patch() as a class decorator, not just as a function decorator. You can then pass in the mocked function as before:

@patch('mymodule.SomeClass')
class MyTest(TestCase):

    def test_one(self, MockSomeClass):
        self.assertIs(mymodule.SomeClass, MockSomeClass)

请参阅: 26.5.3.4.将相同的补丁应用到每种测试方法(其中还会列出替代方法)

See: 26.5.3.4. Applying the same patch to every test method (which also lists alternatives)

如果要对所有测试方法进行修补,则在setUp上以这种方式设置修补程序更有意义.

It makes more sense to set up the patcher this way on setUp if you want the patching to be done for all the test methods.

这篇关于如何在带有unittest setUp的python中正确使用模拟的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-01 19:34