Frage

Ich habe begonnen, Guice mit einigen Dependency Injection an einem Projekt zu tun, vor allem, weil ich Mocks injizieren muß (mit JMock derzeit) einer Schicht weg von dem Gerät zu testen, was sehr umständlich manuelle Injektion macht.

Meine Frage ist, was ist der beste Ansatz ein Modell für die Einführung? Was ich habe, zur Zeit ist ein neues Modul in dem Unit-Test zu machen, dass erfüllt die Abhängigkeiten und binden sie mit einem Anbieter, der wie folgt aussieht:

public class JMockProvider<T> implements Provider<T> {
    private T mock;

    public JMockProvider(T mock) {
        this.mock = mock;
    }

    public T get() {
        return mock;
    }
}

Vorbei an der mock im Konstruktor, so ein JMock Setup könnte wie folgt aussehen:

    final CommunicationQueue queue = context.mock(CommunicationQueue.class);
    final TransactionRollBack trans = context.mock(TransactionRollBack.class);
    Injector injector = Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
            bind(CommunicationQueue.class).toProvider(new JMockProvider<QuickBooksCommunicationQueue>(queue));
            bind(TransactionRollBack.class).toProvider(new JMockProvider<TransactionRollBack>(trans));
        }
    });
    context.checking(new Expectations() {{
        oneOf(queue).retrieve(with(any(int.class)));
        will(returnValue(null));
        never(trans);
    }});
    injector.getInstance(RunResponse.class).processResponseImpl(-1);

Gibt es einen besseren Weg? Ich weiß, dass AtUnit Versuche, dieses Problem zu lösen, obwohl ich vermisse, wie es auto-magisch einen Mock injiziert, die lokal wie die oben erstellt wurden, aber ich bin auf der Suche entweder für einen zwingenden Grund, warum AtUnit die richtige Antwort ist hier (andere als seine Fähigkeit, DI und spöttischen Frameworks um Tests ohne Änderung zu ändern), oder wenn es eine bessere Lösung ist es von Hand zu tun.

War es hilfreich?

Lösung

Sie sollten nicht brauchen Mocks obwohl ein DI Rahmen zu injizieren. Ich bin mit Guice und JMock recht erfolgreich und meine Unit-Tests nichts Guice Zusammenhang verweisen. Ich nur Mocks verwenden und geben in null wo anwendbar.

DI wird die Injektion und das Konstrukt der Abhängigkeiten der aktuellen Klasse ermöglichen, wenn Sie also eine verspottete aus Klasse hinzufügen möchten (die die Abhängigkeitsgraphen effektiv stoppt) Sie müssen nur geben es in. Misko Hevery in einer angegeben von der Google Tech Talk, dass Unit-Tests sollten mit new des und null ist, weil ihr Umfang an die individuellen Einheit Testmethode lokalisiert ist übersät sein. - ich mit ihm zustimmen

Gibt es einen Grund zur Notwendigkeit Guice zu verwenden, in den Tests, das heißt, wenn sie nicht funktionsfähig / Integrationstests?

wäre nicht die Testarbeiten, wenn sie den Injektor ausgeschlossen? Könnten Sie nicht Ihren Test etwas wie Refactoring:

final CommunicationQueue queue = context.mock(CommunicationQueue.class);
final TransactionRollBack trans = context.mock(TransactionRollBack.class);

context.checking(new Expectations() {{
    oneOf(queue).retrieve(with(any(int.class)));
    will(returnValue(null));
    never(trans);
}});

RunResponse r = new RunResponse(queue, trans); // depending on the order
r.processResponseImpl(-1);

Andere Tipps

Von dem, was Sie gesagt habe, es klingt wie Sie nicht einen echten Unit-Test tun. Wenn für eine Klasse Unit-Test zu tun, Sie konzentrieren sich nur auf eine einzige Klasse. Wenn Sie Ihr Gerät-Test ausführen, sollte die Ausführung nur das Thema Klasse ausüben getestet werden und vermeiden Methoden aus verwandten Klassen ausgeführt wird.

JMock / EasyMock sind Werkzeuge, um Hilfe erreichen Ihre Klasse Komponententests. Sie sind in dem Integrationstest nicht sinnvoll.

Im Rahmen der Einheit-Prüfung wird mit Guice JMock / EasyMock überlappt. Guice zwingt Benutzer ihren Code mit allen Arten von Anmerkungen (wie @Inject) verschmutzen das gleiche Ergebnis wie JMock / EasyMock zu erreichen. Ich bin nicht einverstanden wirklich stark mit Guice in der Art, wie sie Hilfe bei der Prüfung. Wenn Entwickler finden sich Guice zu verwenden, anstatt JMock / EasyMock, sie richtig entweder keine echte Unit-Test zu tun oder sie versuchen, Test-Controller-Klassen.

Testing Controller-Klasse soll nicht auf Unit-Test-Ebene erfolgen, sondern auf Integration Testebene. Für Integrationstest ist Jakarta Cactus mit viel hilfreich. Bei Integrationstest, sollten Entwickler haben alle Abhängigkeiten vorhanden, und daher gibt es keine Notwendigkeit Guice zu verwenden.

Als Schlussfolgerung, ich sehe keine Gründe Guice zu verwenden, in ein Produkt zu testen. Google Guice könnte in verschiedenen Kontexten, aber Tests nützlich sein.

Yishai, ich habe das korrigieren ein besseres Design Fahren sollte von Martin Fowler eingeführt Dependency Injection Muster gutgeschrieben. Guice ist ein Werkzeug zur Hilfe, wenn Ihre Codes sind bereits DI Muster gefolgt. Guice trägt nicht etwas zu Ihrem besseren Codierung. Guice löst DI in Ad-hoc-Weise (bei Annotations-Ebene), so dass es nicht als DI-Framework verwendet werden, entweder in Betracht gezogen werden sollte. Das ist der große Unterschied zwischen XML-basierten DI-Containern von Spring und Annotation basierend DI-Containern von Guice.

ich einige Zeit damit verbracht Ihren Code geschrieben am Anfang zu lesen, nur (ich in der Regel nicht) zu verstehen, warum Sie das Gerät zu testen Sie Ihre Klasse nicht möglich ist. Endlich verstehe ich das Problem Sie konfrontiert sind. Von dem, was ich sehe bei Unit-Test-Ebene ist, versuchte man den Ausführungsablauf des Stückes Code zu imitieren, wenn es in Java EE-Server ausgeführt wird. Das ist der Grund, warum Sie stecken geblieben. Ich weiß nicht, was der Anreiz hier, aber ich habe Angst, dass Ihre Bemühungen all diese Umwelt Abhängigkeiten vorbereitet werden verschwendet werden: (

Unit-Test zu schreiben, ist eine „Business-Logik“ zu testen, die von unabhängigen welcher Technik Sie verwenden. Es könnte eine Stillegungs sein besagt, dass diese Geschäftslogik innerhalb von Quality of Service (QoS) Umgebung ausgeführt werden müssen. Diese Anforderung ist „technische Anforderung“. In Ihrem Beispiel CommunicationQueue und Transaction ist meist funktioniert die "technische Anforderung" zu erfüllen. Die Situation ist Ihre „Business-Anforderung“ wird von all diesen Umwelteinheiten umgeben. Was Sie tun sollten, ist Ihr Code Refactoring, so dass Ihre „Business-Anforderung“ in getrennten Verfahren, die keine Abhängigkeiten haben. Dann schreiben Sie Unit-Test für diese Methoden.

Ich halte nach wie vor Ihre Funktionstests tun. Funktionsprüfung bei Unit-Test-Ebene zu tun, ist sehr zeitaufwendig und es ist nicht wert, so etwas zu tun, entweder. Ich hoffe, es hilft

Yishai, klingt wie Sie brauchen, um diese Abhängigkeiten zu gehen um AOP. AspectJ und AspectWerkz sind beide nützliche Ressourcen. Allerdings hat AspectWekz ein sehr schönes Merkmal Aspekt Klassen zur Laufzeit Weben JVM hotswap-Technologie. Natürlich sollte dieser Engineering-Aufwand auf Unit-Tests Ebene gilt nur.

Ich habe viel Mühe gegeben Abhängigkeiten bei der Lösung, wenn Unit-Tests zu tun. Tools wie JMock, EasyMock, Java EE Mikrobehälter, AspectJ, AspectWerkz kann Frühling IoC verwendet werden DI Problem zu lösen. Keines dieser Tools sind die treibende Kraft Entwickler testen Bewusstsein in ihre Produktionscodes setzen. Schade, dass Guice verletzt das Konzept Ihres Codes sauber von allen möglichen Prüfung Bewusstsein zu halten. Und ich zähle es nicht als Werkzeug in meinem Unit-Test verwendet werden.

Ich hoffe, ich habe Ihnen genug Gründe gegeben @Inject Anmerkung von Ihrem Produktionscode zu nehmen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top