2016-06-17 5 views
0

ich derzeit Unit-Tests versucht bin, für meine Main.py die main() FunktionWie kann ich die Einfuhr von anderen Dateien für Unit-Tests außer Kraft setzen

Hier ist eine vereinfachte Version meiner Main.py zu schreiben:

from Configuration import Configuration # Configuration.py is a file in the same dir 

def main(): 
    try: 
    Configuration('settings.ini') 
    except: 
    sys.exit(1) # Test path1 
    sys.exit(0) # Test path2 

if __name__ == '__main__': 
    main() 

in meinem Unit Tests\MainUnitTests.py möchte ich ..\Main.py und fälschen die Configuration Klasse in einer solchen Art und Weise importieren, die ich treffen kann Test path1 und Test path2

ich, dass ich gefundenbehauptenmit den folgenden:

with self.assertRaises(SystemExit) as cm: 
    main() 
self.assertEqual(cm.exception.code, 1) 

aber Ich habe Probleme, die from Configuration import Configuration

Gedanken überschreiben?

Bisher habe ich versucht, die folgenden in Unit Tests\MainUnitTests.py:

class FakeFactory(object): 
    def __init__(self, *a): 
    pass 

sys.modules['Configuration'] = __import__('FakeFactory') 

class Configuration(FakeFactory): 
    pass 

Ein weiteres Beispiel für die Demonstration:

foo.py:

from bar import a,b 

x = a() 

class a(object): 
    def __init__(self): 
    self.q = 2 

y = a() 

print x.q, y.q # prints '1 2' as intended 

b() # I want this to print 2 without modifying bar.py 

bar.py:

class a(object): 
    def __init__(self): 
    self.q = 1 

def b(): 
    t = a() 
    print t.q 
+0

siehe http://stackoverflow.com/questions/5626193/what-is-a-monkey-patch In der Tat ist es die Antwort auf Ihre Frage einschließlich der Beispiele – farincz

+0

@Farincz Affe Patching scheint nicht zu funktionieren. In der MainUnitTest.py importiere ich 'Configuration.py' und erstelle danach' 'class Configuration '' (FakeFactory)' '' '' Main.py's main() 'verwendet jedoch immer noch die Konfigurationsklasse in' Konfiguration.py' es scheint, als ob die beiden Dateien nicht den gleichen globalen Namespace teilen – CaffeineAddiction

+0

müssen Sie Konfiguration und Patch-Konfiguration Attribut auf es importieren und Sie müssen es tun, bevor Main zuerst importiert wird! als es sollte funktionieren – farincz

Antwort

2

, wenn Sie den Import

from bar import a 

es den Namen direkt in das Modul importieren, so bar monkeypatching wird nicht helfen, müssen Sie a direkt in der Hauptdatei außer Kraft zu setzen:

def fake_a(): 
    print("OVERRIDEN!") 

main.a = fake_a 

wissen Sie dass Unittest hat für diese Hilfsfunktionen in the mock subpackage, ich glaube, Sie so etwas wie tun könnte:

from unittest.mock import patch 

... 
with patch("main.a", fake_a) as mock_obj: #there are additional things you can do with the mock_obj 
    do_stuff() 

Dies würde funktionieren in Ihrem ersten Beispiel mit configuration da der Klasse, die gepatcht werden muss, wird im globalen Bereich nicht verwendet, obwohl foobar.a verwendet, sobald es geladen wird, so dass Sie es müßten vor Patch sogar Laden foo:

from unittest.mock import patch 

... 
with patch("bar.a", fake_a) as mock_obj: #there are additional things you can do with the mock_obj 
    import foo #now when it loads it will be loaded with the patched name 

Aber in diesem Fall foo.a würde nicht am Ende des with Block zurückgesetzt werden, weil es nicht von unittest abgefangen werden kann ... Ich hoffe wirklich, dass Ihr tatsächlicher Anwendungsfall das Zeug nicht verwendet, um auf Modul-Ebene gepatcht zu werden.