2017-10-12 2 views
3

innerhalb eines eingeführten Verfahren aus verschiedenen Modul importiert habe ich die folgende Funktion zu testen:Wie eine Funktion verspotten, dass

my_package.db_engine.db_functions.py:

from ..utils import execute_cmd 
from my_package.db_engine.db_functions import dbinfo 

def dbinfo(db_name): 
    params = (cmd_cfg.DB, add_pj_suffix(db_name)) 
    cmd = get_db_cmd_string(cmd_cfg.DBINFO, params=params) 
    cmd_result = execute_cmd(cmd) 
    result_dict = map_cmd_output_to_dict(cmd_result) 
    return result_dict 

Diese Funktion Nimmt den Namen einer Datenbank an, erstellt daraus eine Befehlszeichenfolge und führt diesen Befehl als subprocess mit der Methode execute_cmd aus. Ich möchte diese Funktion testen, ohne die subprocess tatsächlich auszuführen. Ich möchte nur überprüfen, ob der Befehl korrekt erstellt und korrekt an execute_cmd übergeben wurde. Deshalb muss ich die execute_cmd Methode vortäuschen, die von Modul utils importiert wird.

Meine Ordnerstruktur ist die folgende:

my_project 
|_src 
| |_my_package 
| | |_db_engine 
| | | |_db_functions.py 
| | | |_ __init__.py 
| | |_utils.py 
| | |_ __init__.py 
| | |_ .... 
| |_ __init__.py 
|_tests 
    |_test_db_engine.py 

Also für meinen Test habe ich versucht, die folgenden in test_db_engine.py:

import unittest 
from mock import patch 

from my_pacakge.db_engine.db_functions import dbinfo 


def execute_db_info_cmd_mock(): 
    return { 
      'Last Checkpoint': '1.7', 
      'Last Checkpoint Date': 'May 20, 2015 10:07:41 AM' 
    } 


class DBEngineTestSuite(unittest.TestCase): 
    """ Tests für DB Engine""" 

    @patch('my_package.utils.execute_cmd') 
    def test_dbinfo(self, test_patch): 
     test_patch.return_value = execute_db_info_cmd_mock() 
     db_info = dbinfo('MyDBNameHere') 
     self.assertEqual(sandbox_info['Last Checkpoint'], '1.7') 

Die Ausführung der eigentlichen Befehl Erträge 1.6 für Last Checkpoint. Um zu überprüfen, ob der Schein-Rückgabewert verwendet wird, setze ich ihn auf 1.7. Aber der Mock für die Funktion wird nicht verwendet, da die Ausführung des Testfalls immer noch 1.6 ergibt, weil es die eigentliche Funktion ausführt, die mit dem Mock gepatcht werden sollte.

Irgendeine Idee, was ich hier falsch gemacht habe?

Antwort

3

Sie patchen den falschen Ort. Von der Where to patch section:

patch() Werke (vorübergehend) zu ändern, das Objekt, dass ein Name Punkte mit einem anderen. Es kann viele Namen geben, die auf ein einzelnes Objekt verweisen. Um das Patchen zu ermöglichen, müssen Sie sicherstellen, dass Sie den Namen des zu testenden Systems patchen.

Das Grundprinzip ist, dass Sie Patch, wo ein Objekt ist nachgeschlagen, die nicht unbedingt an der gleichen Stelle, wo es definiert ist.

Ihr Code-under-Test execute_cmd als global in ihrem eigenen Modul findet, muss man aber, dass der Bezug nicht patchen:

from ..utils import execute_cmd 

Die my_package.utils.execute_cmd Referenz gepatcht ist, aber die execute_cmd Referenz in my_package.db_engine.db_functions wird immer noch auf die ursprüngliche, nicht gepatchte Funktion zeigen.

die globale stattdessen importiert Patch:

@patch('my_package.db_engine.db_functions.execute_cmd') 

Nun ist die execute_cmd Lookup innerhalb dbinfo das gepatchte Mock-Objekt verwenden, anstatt der ursprünglichen globalen durch die Aussage from ... import ... gebunden.

+0

Vielen Dank, das hat richtig funktioniert =) – Igle

Verwandte Themen