Bei meinem Versuch, TDD zu lernen, versuche ich, Unit-Tests zu lernen und Mock mit Python zu verwenden. Langsam den Dreh raus, aber unsicher, ob ich das richtig mache. Vorgewarnt: Ich arbeite nicht mit Python 2.4, da die Hersteller-APIs als vorkompilierte 2.4-Pyc-Dateien vorliegen. Daher verwende ich Mock 0.8.0 und unittest (nicht unittest2).
Angesichts dieses Beispielcodes 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
Jetzt möchte ich in meiner Testfalldatei 'test_myclass.py' das ldap-Objekt verspotten. ldap.initialize gibt das ldap.ldapobject.SimpleLDAPObject zurück, also dachte ich mir, das wäre die Methode, die ich verspotten müsste.
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
Führt mich zu ein paar Fragen:
- Sieht das richtig aus :) :)
- Ist das der richtige Weg, um ein Objekt zu verspotten, das innerhalb der Klasse, die ich teste, instanziiert wird?
- Ist es in Ordnung, den @ Patch-Dekorateur bei setUp anzurufen, oder führt dies zu seltsamen Nebenwirkungen?
- Gibt es überhaupt eine Möglichkeit, die Ausnahme ldap.INVALID_CREDENTIALS auszulösen, ohne die Ausnahme in meine Testfalldatei importieren zu müssen?
- Sollte ich stattdessen patch.object () verwenden und wenn ja, wie?
Vielen Dank.
import ldapstattdessen und setzenside_effect = ldap.INVALID_CREDENTIALS?