Ich habe eine Fabrik geschrieben, um java.sql.Connection
Objekte herzustellen :
public class MySQLDatabaseConnectionFactory implements DatabaseConnectionFactory {
@Override public Connection getConnection() {
try {
return DriverManager.getConnection(...);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
Ich möchte die übergebenen Parameter überprüfen DriverManager.getConnection
, weiß aber nicht, wie ich eine statische Methode verspotten soll. Ich verwende JUnit 4 und Mockito für meine Testfälle. Gibt es eine gute Möglichkeit, diesen speziellen Anwendungsfall zu verspotten / zu verifizieren?
java
unit-testing
mocking
mockito
Naftuli Kay
quelle
quelle
static
, sondern aus Versehen . Diese Einschränkung (zusammen mit keiner Unterstützung für das Verspotten vonfinal
Klassen / Methoden odernew
-ed-Objekten) ist eine natürliche (aber unbeabsichtigte) Folge des Ansatzes zum Implementieren von Mocking, bei dem neue Klassen dynamisch erstellt werden, die den zu verspottenden Typ implementieren / erweitern. Andere Spottbibliotheken verwenden andere Ansätze, die diese Einschränkungen vermeiden. Dies geschah auch in der .NET-Welt.Antworten:
Verwenden Sie PowerMockito über Mockito.
Beispielcode:
Mehr Informationen:
quelle
@RunWith(PowerMockRunner.class)
und darunter@PowerMockRunnerDelegate(JUnit4.class)
.Die typische Strategie, um statischen Methoden auszuweichen, die Sie nicht vermeiden können, besteht darin, umschlossene Objekte zu erstellen und stattdessen die Wrapper-Objekte zu verwenden.
Die Wrapper-Objekte werden zu Fassaden für die realen statischen Klassen, und Sie testen diese nicht.
Ein Wrapper-Objekt könnte so etwas wie sein
Schließlich kann Ihre zu testende Klasse dieses Singleton-Objekt verwenden, indem Sie beispielsweise einen Standardkonstruktor für die Verwendung im realen Leben haben:
Und hier haben Sie eine Klasse, die leicht getestet werden kann, da Sie eine Klasse mit statischen Methoden nicht direkt verwenden.
Wenn Sie CDI verwenden und die Annotation @Inject verwenden können, ist dies noch einfacher. Machen Sie einfach Ihre Wrapper-Bean @ApplicationScoped, lassen Sie das Ding als Kollaborateur injizieren (Sie brauchen nicht einmal unordentliche Konstruktoren zum Testen) und fahren Sie mit dem Verspotten fort.
quelle
Ich hatte ein ähnliches Problem. Die akzeptierte Antwort hat bei mir nicht funktioniert, bis ich die Änderung vorgenommen habe:
@PrepareForTest(TheClassThatContainsStaticMethod.class)
Laut PowerMock-Dokumentation für mockStatic .Und ich muss nicht verwenden
BDDMockito
.Meine Klasse:
Meine Testklasse:
quelle
Wie bereits erwähnt, können Sie statische Methoden mit mockito nicht verspotten.
Wenn das Ändern Ihres Testframeworks nicht möglich ist, können Sie Folgendes tun:
Erstellen Sie eine Schnittstelle für DriverManager, verspotten Sie diese Schnittstelle, fügen Sie sie über eine Art Abhängigkeitsinjektion ein und überprüfen Sie diese.
quelle
Beobachtung: Wenn Sie eine statische Methode innerhalb einer statischen Entität aufrufen, müssen Sie die Klasse in @PrepareForTest ändern.
Zum Beispiel:
Verwenden Sie für den obigen Code, wenn Sie die MessageDigest-Klasse verspotten müssen
Während, wenn Sie etwas wie unten haben:
Dann müssen Sie die Klasse vorbereiten, in der sich dieser Code befindet.
Und dann verspotten Sie die Methode:
quelle
Sie können es mit ein wenig Refactoring tun:
Dann können Sie Ihre Klasse erweitern
MySQLDatabaseConnectionFactory
, um eine verspottete Verbindung zurückzugeben, Aussagen zu den Parametern zu machen usw.Die erweiterte Klasse kann sich im Testfall befinden, wenn sie sich im selben Paket befindet (wozu ich Sie ermutige).
quelle
Um eine statische Methode zu verspotten, sollten Sie einen Powermock-Look verwenden: https://github.com/powermock/powermock/wiki/MockStatic . Mockito bietet diese Funktionalität nicht an.
Sie können einen Artikel über Mockito lesen: http://refcardz.dzone.com/refcardz/mockito
quelle
Mockito kann keine statischen Methoden erfassen, aber seit Mockito 2.14.0 können Sie es simulieren, indem Sie Aufrufinstanzen statischer Methoden erstellen.
Beispiel (aus ihren Tests extrahiert ):
Ihr Ziel ist es nicht, statisches Mocking direkt zu unterstützen, sondern die öffentlichen APIs zu verbessern, damit andere Bibliotheken wie Powermockito nicht auf interne APIs angewiesen sind oder direkt Mockito-Code duplizieren müssen. ( Quelle )
quelle
Ich habe auch eine Kombination aus Mockito und AspectJ geschrieben: https://github.com/iirekm/varia/tree/develop/ajmock
Ihr Beispiel wird:
quelle
Da diese Methode statisch ist, verfügt sie bereits über alles, was Sie zur Verwendung benötigen, sodass der Zweck des Verspottens zunichte gemacht wird. Das Verspotten der statischen Methoden wird als schlechte Praxis angesehen.
Wenn Sie dies versuchen, bedeutet dies, dass etwas mit der Art und Weise, wie Sie Tests durchführen möchten, nicht stimmt.
Natürlich können Sie PowerMockito oder ein anderes Framework verwenden, das dazu in der Lage ist, aber versuchen Sie, Ihren Ansatz zu überdenken.
Beispiel: Versuchen Sie, die Objekte zu verspotten / bereitzustellen, die diese statische Methode stattdessen verwendet.
quelle
Verwenden Sie das JMockit-Framework . Es hat bei mir funktioniert. Sie müssen keine Anweisungen schreiben, um die Methode DBConenction.getConnection () zu verspotten. Nur der folgende Code ist genug.
@Mock unten ist mockit.Mock-Paket
quelle