Sollte jede Methode einen Wert für Unit Testing zurückgeben?

12

Ich lerne, einfache Unit-Tests zu erstellen, um irgendwann (und hoffentlich) nur noch TDD zu machen. Im Moment versuche ich, Tests für bereits geschriebenen Code zu schreiben, um festzustellen, was Probleme verursachen könnte. Dies ist einer von ihnen.

Angenommen, ich habe diese einfache Klasse (mit Typescript-> Javascript):

class PrivateStuff {
    greeting: string;
    private _thisIsPrivate;

    constructor(isPrivate: boolean) {
        this._thisIsPrivate = isPrivate;
    }

    setPrivate(option) {
        this._thisIsPrivate = option;
        console.log("_thisIsPrivate changed to : " + option);
    }

    getPrivate() {
        console.log("_thisIsPrivate is : " + this._thisIsPrivate);
        return this._thisIsPrivate;        
    }
}

Und ich benutze es so:

let privateStuff = new PrivateStuff(false);

let buttonSet = document.createElement('button');
buttonSet.textContent = "Set True";
buttonSet.onclick = function () {
    privateStuff.setPrivate(true);
}

let buttonGet = document.createElement('button');
buttonGet.textContent = "Get";
buttonGet.onclick = function() {
    console.log(privateStuff.getPrivate());
}
document.body.appendChild(buttonSet);
document.body.appendChild(buttonGet);

setPrivate()muss nichts zurückgeben, kann es aber deshalb nicht testen. Sollte ich beim Erstellen eines Komponententests den Code umgestalten?

Wenn ich TDD mache, sollte ich immer Methoden erstellen, die etwas zurückgeben, nur um es testen zu können? Oder fehlt mir etwas?

PS Sie können den Code hier sehen und ausführen

distante
quelle
4
Wenn Sie setPrivate setzen, sagt Ihnen der Wert von getPrivate nicht, ob es funktioniert hat?
JeffO
@ JeffO Ja, ich sehe jetzt, dass ich nicht nur die Rückgabe der Funktion verwenden muss, um zu überprüfen, ob es funktioniert hat.
distante
"setPrivate () muss nichts zurückgeben, aber aus diesem Grund kann ich es nicht testen." Verursacht es einen beobachtbaren Effekt? Wenn ja, können Sie es testen. Andernfalls besteht kein Interesse daran, es zu testen (und es besteht kein Interesse daran, es zu implementieren).
Mgoeminne
@mgoeminne Was ist, wenn die Methode ungültig ist und in die Datenbank / das Protokoll schreibt oder als einzige Auswirkung eine Nachricht an ein anderes Objekt sendet?
Andres F.
@AndresF. Sie können aus der Datenbank / dem Protokoll lesen oder das andere Objekt verspotten, um zu bestätigen, dass die Daten gesendet wurden. Es ist vielleicht kein "Unit" -Test, aber darauf kommt es eigentlich nicht an.
Jacob Raihle

Antworten:

21

Ich denke, Ihr Missverständnis hier ist, dass ein "zu testendes Subjekt" immer eine Methode für sich sein muss. Dies ist jedoch nicht der Fall, obwohl einige Methoden ohne Verwendung anderer Methoden getestet werden können. Die typische Größe eines SUT ist eine Klasse oder einige interagierende Methoden und Funktionen einer Klasse. Wenn Sie also eine Methode haben, die den internen Status eines Objekts ändert, muss das Verhalten dieses Objekts immer von außen sichtbar geändert werden (andernfalls wäre es nicht sinnvoll, die Methode überhaupt zu haben). Und in einem Unit-Test können Sie genau dieses Verhalten validieren.

Angenommen, Sie haben eine Klasse, die dafür NumberFormatterverantwortlich ist, Gleitkommazahlen vordefiniert zu formatieren. Nehmen wir an, es enthält eine Methode FormatToString(double d). Nehmen wir weiter an, es hat eine Methode setDecimalSeparator, aber nein getDecimalSeparator. Trotzdem können Sie leicht einen Test schreiben, wenn sich setDecimalSeparatordie Methode nach einem Aufruf der Methode FormatToStringwie gewünscht verhält. Ein solcher Test könnte so aussehen

  var nf = new NumberFormatter();
  nf.setDecimalSeparator(".");
  AssertEqual("12.34",nf.FormatToString(12.34))
  nf.setDecimalSeparator(",");
  AssertEqual("12,34",nf.FormatToString(12.34))

Dies ist also ein aussagekräftiger Test setDecimalSeparatoreiner Methode ohne Rückgabewert.

Doc Brown
quelle
Ich verstehe, also könnte ich in meinem unrealistischen Beispiel die Funktion ´getPrivate () ´ verwenden, um zu sehen, ob sich ´_thisIsPrivate´ geändert hat, und muss annehmen, dass ´getPrivate () ´ funktioniert, aber in einem realistischeren Szenario sollte ich das zu ändernde Objekt testen . Vielen Dank für Ihre klare Erklärung!
distante