2016-04-12 12 views
0

search_ldap()という名前の関数のunittestを作成しようとしています。これは、特定のユーザー名を指定してLDAPサーバーを検索します。ここでutils.pyでの関数の定義は、(:私は、Python 3を使用しています注意してください):あるもちろんutils.pyのDjango unittestでモックが失敗する

from ldap3 import Server, Connection 
def search_ldap(username): 
    result =() 
    baseDN = "o=Universiteit van Tilburg,c=NL" 
    searchFilter = '(uid={})'.format(username) 
    attributes = ['givenName', 'cn', 'employeeNumber', 'mail'] 

    try: 
     server = Server('ldap.example.com', use_ssl=True) 
     conn = Connection(server, auto_bind=True) 
     conn.search(baseDN, searchFilter, attributes=attributes) 
     for a in attributes: 
      result += (conn.response[0]['attributes'][a][0],) 
    except Exception: 
     raise LDAPError('Error in LDAP query') 

    return result 

私は実際にテスト中ldap.example.comに接続したくないので、私はPythonのmock object libraryを使うことにしました私のunittestsにServer()Connection()のクラスを偽ってください。

from unittest import mock 
from django.test import TestCase 
class LdapTest(TestCase): 
    @mock.patch('ldap3.Server') 
    @mock.patch('ldap3.Connection') 
    def test_search_ldap(self, mockConnection, mockServer): 
     from .utils import search_ldap 
     search_ldap('username') 
     self.assertTrue(mockServer.called) 
     self.assertTrue(mockConnection.called) 

このテストでは、模擬されたサーバーオブジェクトと接続オブジェクトがインスタンス化されていることを単純にアサートしています。

Creating test database for alias 'default'... 
F. 
====================================================================== 
FAIL: test_search_ldap (uvt_user.tests.LdapTest) 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "/usr/lib/python3.4/unittest/mock.py", line 1142, in patched 
    return func(*args, **keywargs) 
    File "/home/jj/projects/autodidact/uvt_user/tests.py", line 28, in test_search_ldap 
    self.assertTrue(mockServer.called) 
AssertionError: False is not true 

---------------------------------------------------------------------- 
Ran 2 tests in 0.030s 

FAILED (failures=1) 
Destroying test database for alias 'default'... 

はなぜ私のテストが失敗している:私は./manage.py testでテストを実行したとき、私は次のエラーが表示されているためしかし、持ち運びにくいが、ではないのですか?どうすればldap3のサーバークラスと接続クラスを正常にモックできますか?

答えて

0

モッククラスには、必要なメソッドを使って偽の実装を提供する必要があります。たとえば:patch()

class FakeServer: 
    def call(): 
     pass 

class LdapTest(TestCase): 
    @mock.patch('ldap3.Server', FakeServer) 
    def test_search_ldap(self): 
     <do you checks here> 
+0

まあ、[ドキュメント](に従ってhttps://docs.python.org/dev/library/ unittest.mock.html#quick-guide)、偽の実装を残して、単一の引数で 'patch()'を呼び出すこともできます。それでも、私はあなたの解決策を試しました。そして、utils.pyは、模倣されたものではなくオリジナルの 'ldap3'モジュールをまだインポートしています。 – hedgie

0

は、あなたがそれらが検索される名前空間内のオブジェクトにパッチを適用することが重要です。これは、ドキュメントのWhere to patchセクションで説明されています。

from ldap3 import Server 
server = Server() 

第1ケース(元の質問でも、場合)には

import ldap3 
server = ldap3.Server() 

を行う間には根本的な違いがあり、名前「サーバー」とは、現在のモジュールに属します。後者の場合、「Server」という名前はldap3モジュールに属しています。次Djangoはunittestの正しい「サーバー」と「接続」の名前をパッチし、意図したとおりに動作するはずです:

from unittest import mock 
from django.test import TestCase 
class LdapTest(TestCase): 
    @mock.patch('appname.utils.Server') 
    @mock.patch('appname.utils.Connection') 
    def test_search_ldap(self, mockConnection, mockServer): 
     from .utils import search_ldap 
     search_ldap('username') 
     self.assertTrue(mockServer.called) 
     self.assertTrue(mockConnection.called) 
関連する問題