Introduction
Dependencies injected by Guice are generally created using annotated constructor. But sometimes you need a generator of specific class objects or you have to initialize your class before using it. These goals you can meet using providers. First, suppose you have ReportController, which stores given message with actual date in some place (database, file).
Injecting Provider
If you want to write good unit tests, you should protect yourself against changing date, so you can inject a kind of date generator - Provider of Date.
public class DateProviderTest { @Test public void shouldGetAnotherTimeForEachGet() throws InterruptedException { // given Injector injector = Guice.createInjector(); Provider<Date> sut = injector.getProvider(Date.class); // when Date firstDate = sut.get(); Thread.sleep(1); Date secondDate = sut.get(); // then assertNotNull(firstDate); assertNotNull(secondDate); assertNotEquals(firstDate.getTime(), secondDate.getTime()); } }
In unit tests for classes, which use this provider you only need to mock Provider interface and return fixed date on each call.
Injecting via provider
Sometimes your objects should be additionally prepared before using, for example you have to call initialize method. It also could be done in described above way or you could use ProvidedBy annotation and explicit define Provider for your class. First, let's define class which should be initialized before using:
@ProvidedBy(ReportSessionFactory.class) public class ReportSession { private boolean initialized; public ReportSession() {} public void init() { this.initialized = true; } public boolean isInitialized() { return initialized; } public boolean report(final String reportMessage, final Date date) { if(!initialized){ return false; } // ... return true; } }
ProvidesBy points to class which implements Provider interface:
public class ReportSessionFactory implements Provider<ReportSession> { @Override public ReportSession get() { ReportSession reportSession = new ReportSession(); reportSession.init(); return reportSession; } }
Now when we will inject object of class ReportSession it will be given to us from provider and already initialized:
public class ReportSessionProviderTest { @Test public void shouldInitReportSession() { // given Injector injector = Guice.createInjector(); ReportSession sut = injector.getInstance(ReportSession.class); // when boolean result = sut.isInitialized(); // then assertTrue(result); } }
Conclusion
When you need to inject a generator of runtime dependent objects or have to call method of dependency immediately after constructor, Guice providers are the best options for you. Sources are available here.
No comments:
Post a Comment