2013-04-16 23 views
34

Ich habe eine Java-Klasse voller void-Methoden, und ich möchte einige Unit-Test machen, um maximale Code-Abdeckung zu bekommen.JUNIT Tests void Methoden

Zum Beispiel habe ich diese Methode:

protected static void checkifValidElements(int arg1, int arg2) { 
    method1(arg1); 
    method2(arg1); 
    method3(arg1, arg2); 
    method4(arg1, arg2); 
    method5(arg1); 
    method6(arg2); 
    method7(); 
} 

Sein schlecht für einen Grund genannt, weil ich den Code für ein besseres Verständnis übersetzt. Jede Methode überprüft, ob die Argumente in irgendeiner Weise gültig und gut geschrieben sind.

Beispiel:

private static void method1(arg1) { 
    if (arg1.indexOf("$") == -1) { 

     //Add an error message 
     ErrorFile.errorMessages.add("There is a dollar sign in the specified parameter"); 
    } 
} 

My Unit-Test decken die kleinen Methoden in Ordnung, weil ich sie bitten, zu prüfen, ob die Fehlerdatei die Fehlermeldung enthält, aber ich sehe nicht, wie ich meine Methode checkIfValidElements testen können, gibt sie nichts oder nichts ändern. Wenn ich Code-Coverage mit Maven führe, sagt es mir, dass der Unit-Test-Doesent diesen Teil meiner Klasse abdeckt.

Der einzige Weg, ich sehe, ist diese Methode zu ändern, um einen int oder bollean Wert zurückgeben, wie folgt aus:

protected static int checkifValidElements(int arg1, int arg2) { 
    method1(arg1); 
    method2(arg1); 
    method3(arg1, arg2); 
    method4(arg1, arg2); 
    method5(arg1); 
    method6(arg2); 
    method7(); 
    return 0; 
} 

Mit dieser Methode ich in der Lage bin eine Assertion zu tun ist gleich, aber es scheint mir, dass es ist zwecklos, dies zu tun. Das Problem ist, dass ich ein paar Klassen habe, die so aussehen und die Testabdeckung meiner Einheit verringern.

+0

Ich verstehe nicht, wie Rückgabetyp einer Methode Abdeckung wirkt. Asserts sind für die Berichterstattung ebenfalls irrelevant. Die einzige Tatsache ist wichtig - führen Sie eine Methode während eines Komponententests aus oder nicht. – kan

Antwort

43

Ich möchte einige Unit-Test machen maximale Codeabdeckung

Code-Coverage bekommen sollte nie schreiben Unit-Tests die Ziel sein. Sie sollten Komponententests schreiben, um zu beweisen, dass Ihr Code korrekt ist, oder Ihnen helfen, ihn besser zu gestalten, oder anderen helfen, zu verstehen, wozu der Code gedacht ist.

aber ich sehe nicht, wie ich meine Methode checkIfValidElements testen kann, gibt nichts zurück oder ändert nichts.

Nun sollten Sie wahrscheinlich ein paar Tests geben, die zwischen ihnen überprüfen, ob alle 7 Methoden in geeigneter Weise genannt werden - sowohl mit einem ungültigen Argument und mit einem gültigen Argument, die Ergebnisse der ErrorFile jedes Mal zu überprüfen.

Zum Beispiel entfernt Angenommen, jemand den Anruf an:

method4(arg1, arg2); 

... oder geändert versehentlich das Argument um:

method4(arg2, arg1); 

Wie würden Sie diese Probleme bemerkt? Gehen Sie davon weg und entwerfen Sie Tests, um es zu beweisen.

+0

Danke! Ich bin immer noch neu in Unit Tests, und ich denke zu sehr auf eine lineare/komplexe Art und Weise. Ich werde die Tests vereinfachen und diese Tests variieren, um mehr "Abdeckung" oder mögliche Fälle zu Tests zu bekommen. – metraon

+0

"Code-Coverage sollte niemals das Ziel sein, Komponententests zu schreiben" Könnten Sie etwas genauer erklären? – Gobliins

+6

@Gobliins: Codeabdeckung ist eine Nummer. Wenn die Zahl steigt, ohne dass Sie tatsächlich mehr Vertrauen in die Zuverlässigkeit Ihres Codes haben, was ist der Sinn? Das Ziel sollte sein, die Qualität des Codes zu verbessern (sowohl Design als auch Implementierung). Abdeckung ist ein * möglicher * Indikator dafür, aber es ist durchaus möglich, gute Tests für kritische und komplexe Aspekte Ihres Codes zu haben und immer noch relativ geringe Abdeckung - oder haben eine hohe Abdeckung, aber schlechte Tests. –

3

Sie können immer noch eine void-Methode testen, indem Sie die entsprechende Nebenwirkung bestätigen. In Ihrem method1 Beispiel könnte Ihr Unit-Test in etwa so aussehen:

public void checkIfValidElementsWithDollarSign() { 
    checkIfValidElement("$",19); 
    assert ErrorFile.errorMessages.contains("There is a dollar sign in the specified parameter"); 
} 
1

Ich denke, Sie sollten schriftlich Neben Bewirkung Verfahren zu vermeiden. Geben Sie wahr oder falsch von Ihrer Methode zurück, und Sie können diese Methoden in Komponententests überprüfen.

15

Wenn Ihre Methode keine Nebenwirkungen hat, und gibt nichts zurück, dann ist es nichts zu tun.

Wenn Ihre Methode eine Berechnung tut und gibt das Ergebnis dieser Berechnung können Sie offensichtlich genug behaupten, dass das Ergebnis zurückgegeben korrekt ist.

Wenn Ihr Code nicht wieder etwas, aber Nebenwirkungen hat, können Sie den Code aufrufen und dann behaupten, dass die richtigen Nebenwirkungen geschehen. Was die Nebenwirkungen sind, wird bestimmen, wie Sie die Kontrollen durchführen.

In Ihrem Beispiel rufen Sie statische Methoden von Ihren Nicht-Rückkehr-Funktionen, die es schwierig, wenn Sie, dass das Ergebnis all diesen statischen Methoden richtig sind inspizieren machen. Ein besserer Weg - aus der Sicht von Tests - besteht darin, tatsächliche Objekte zu injizieren, in denen Methoden aufgerufen werden. Sie können dann etwas wie EasyMock oder Mockito verwenden, um ein Mock-Objekt in Ihrem Komponententest zu erstellen und das Mock-Objekt in die Klasse zu injizieren. Mit dem Mock-Objekt können Sie dann bestätigen, dass die korrekten Funktionen mit den richtigen Werten und in der richtigen Reihenfolge aufgerufen wurden.

Zum Beispiel:

private ErrorFile errorFile; 

public void setErrorFile(ErrorFile errorFile) { 
    this.errorFile = errorFile; 
} 

private void method1(arg1) { 
    if (arg1.indexOf("$") == -1) { 

     //Add an error message 
     errorFile.addErrorMessage("There is a dollar sign in the specified parameter"); 
    } 
} 

Dann in Ihrem Test können Sie schreiben:

public void testMethod1() { 
    ErrorFile errorFile = EasyMock.createMock(ErrorFile.class); 
    errorFile.addErrorMessage("There is a dollar sign in the specified parameter"); 
    EasyMock.expectLastCall(errorFile); 
    EasyMock.replay(errorFile); 

    ClassToTest classToTest = new ClassToTest(); 
    classToTest.setErrorFile(errorFile); 
    classToTest.method1("a$b"); 

    EasyMock.verify(errorFile); // This will fail the test if the required addErrorMessage call didn't happen 
} 
+0

Ich werde in das graben. Danke – metraon

+1

<< Wenn Ihre Methode keine Nebenwirkungen hat und nichts zurückgibt, dann tut sie nichts. >> Das ist nicht wahr, was ist, wenn Ihre Methode nur den Zustand des Objekts ändert? – magulla

+7

Das ist ein Nebeneffekt, es ändert etwas – tddmonkey

1

Sie können etwas namens „spöttisch“ lernen. B. prüfen, ob: - eine Funktion aufgerufen wurde - eine Funktion wurde x mal aufgerufen - eine Funktion wurde mindestens x mal aufgerufen - eine Funktion wurde mit einem bestimmten Parametersatz aufgerufen. In Ihrem Fall zum Beispiel, können Sie mit dem, was Sie passieren, wie arg1 und arg2 verwenden spöttisch, dass method3 überprüfen wurde einmal genannt.

Werfen Sie einen Blick auf diese: https://code.google.com/p/mockito/ https://code.google.com/p/powermock/