A question about Guice. I'm still learning it, but I can understand the fundamentals.
This question was already asked a couple of times on the net, but never with a concrete answer(none that I could find).
Say I have a situation like on the picture(a similar example was somewere on the net).
public class Dog {}
public class Walk implements Walkable {
private final Dog dog;
private final boolean leash;
#Inject
public Walk(Dog dog, #Assisted boolean leash) {
this.dog = dog;
this.leash = leash;
}
public void go() {
}
}
public interface Walkable {
void go();
}
public interface WalkFactory {
Walk create(boolean leash);
}
public class AssistedMain {
public static void main(String[] args) {
Injector i = Guice.createInjector(new AbstractModule() {
protected void configure() {
install(new FactoryModuleBuilder().
implement(Walkable.class, Walk.class).
build(WalkFactory.class));
}
});
Walk walk = i.getInstance(WalkFactory.class).create(true);
}
}
That's all great. But the question is - can I, somehow, reinject that object instance to the "container"(injector) to be used on the classes that rely on this dependency.
So, lets add a interface Person, class PersonImpl.
The new classes source are:
public interface Person {
void walkDog();
}
public class PersonImpl implements Person {
private Walkable walkable;
#Inject
public PersonImpl(Walkable walkable) {
this.walkable = walkable;
}
public void setWalkable(Walkable walkable) {
this.walkable = walkable;
}
public void walkDog() {
walkable.go();
}
}
So, the question is - am I, somehow able to actually inject this particular instance into the added object. This is a simple example, but we can presume there are 10 levels of classes below this one.
The solution I found is not very flexible. Something like:
Injector i = Guice.createInjector(new SimpleModule(false, dog));
And then bind to concrete instance. That's not very dynamic. Basically, every time I need a different runtime/dynamic parameter I have to recreate the injector.
The Provider<T> is nice, the FactoryModuleBuilder helps, but how can I inject the objects back?
Are there more dynamic solutions to this problem?
Thanks.
MPierce - agreed. Ill try to explain the way i visualized the problem(you can correct me if im wrong).
Being originaly derived from a "service locator" pattern, the idea that it can manage more than services is optimistic to say the least.
We could split the application into Service and Data classes, or you could say that we have application and infrastructure code - "Dependency Injection", a great book.
So, basicly, dependecy injection, and dependency injection frameworks in general are great. For solving infrastructure, or "service" code.
Any dynamic(runtime) parameters being injected into the Container/Injector are basicly forcing you to end the object graph.
For example, we have the folowing design:
EmailMessage is a runtime parameter. It can be "injected" into email service outside the Container/Injector, but it ends the object graph. If we want to request EmailDispatcher, after we injected the EmailMessage into EmailService(which is, I repeat, done outside injector), we could no longer fetch EmailDispatcher from the injector.
Then, you could redesign your model so it "fits" into the Container/Injector concept of dynamic parameters.
But then again, you forced the design, and suddenly, EmailDispatcher has too many responsibilites. It could be used in such a context, where you dont have many infrastructure classes.
And when you have a design like you have in the third example picture, you cannot use the Injector/Container to fetch you a NextService3 instance(nor any below the level of EmailDispatcher).
The problem being - if you have any dynamic(runtime) parameters, you can only use dependency injection for classes above the class that requires a dynamic parameter, you can forget the classes below.
Phew.
Correct?
Part of the problem depends on how you're resolving that 'false' is the thing you want to set for the leash field. Is that coming from config data or what?
A provider method may be helpful...
class FooModule extends AbstractModule {
...
#Provides
Walkable getWalkable(Dog dog) {
boolean leash = getBooleanFromSomewhere();
return new Walk(dog, leash);
}
}
If you can clarify where that boolean is coming from, it'll help me to understand what type of approach is applicable.
You can use custom scopes, much like when using guice servlets. That way you can create your instance, and then seed it in the injector.
Related
I am having a abstract super class TP and which have a concrete sub class ETP. This is my code:
abstract class TP {
private Configuration app;
protected MC bMC() {
}
}
and sub class ETP code is:
public class ETP extends TP {
private Configuration app;
public MC pT() {
bMC();
}
}
I am writing test case for ETP which is ETPTest which looks like this
public class ETPTest {
#Before
public void setUp() throws Exception {
// as TP is abstract i am initializing with ETP
TP = new ETP();
// some initialization
}
Whitebox.setInternalState(TP, app);
}
but app is getting passed as null in TP and getting NPE in TP.
any ideas or suggestions?
app is a private variable defined in both TP and ETP; and I am trying to set internal state for app which is in TP.
Your difficulties to such things can be seen as a symptom.
You can decide that the cure is to spent hours until you get the mocking parts to circumvent around that problem.
Whereas the other option is: understand that the given design is deficient:
sub classes should absolutely not care about private fields in super classes. The whole point of private is to make things an "implementation detail" that no other class should know or care about
Worse: by putting up a second private field with the same name, you just added to that confusion. Those will be to different private fields; there is no "overriding" or "polymorphism" here.
In the end, you probably do not understand how to properly design a solution that uses inheritance and abstract base classes. You should thus step back, and think for example, if a solution like this helps:
public abstract class Base {
protected abstract Configuration getConfiguration();
public final void doSomething() {
... calls getConfiguration() to do its jobs
}
}
and then:
public abstract class Subclass extends Base {
protected Configuration getConfiguration() {
return whatever
As a rule of thumb: clean, straight-forward, non-surprising designs can most often be unit tested simply by using dependency injection and one mock here and another one there. As soon as you have to look into all these complex "solutions"; such as mocking super-class methods/fields; or mocking static methods, ... you are already suffering from a bad design; and instead of fixing that problem; you try to work around it.
That will not help you in the long run. Because the real problem is the "smelly" design in your production code.
Code from Spring in Action :
public class DamselRescuingKnight implements Knight {
private RescueDamselQuest quest;
public DamselRescuingKnight() {
this.quest = new RescueDamselQuest();
}
public void embarkOnQuest() {
quest.embark();
}
}
public class BraveKnight implements Knight {
private Quest quest;
public BraveKnight(Quest quest) {
this.quest = quest;
}
public void embarkOnQuest() {
quest.embark();
}
}
public class BraveKnightTest {
#Test
public void knightShouldEmbarkOnQuest() {
Quest mockQuest = mock(Quest.class);
BraveKnight knight = new BraveKnight(mockQuest);
knight.embarkOnQuest();
verify(mockQuest, times(1)).embark();
}
}
I understand the use of dependency injection, which allows us to switch implementation without modifying the depending code.
The book says "terribly difficult to write a unit test ...".
However, I am not able to understand how it will be very difficult for unit-testing without dependency injection! My intuition refuses to co-operate !
Can you start writing junit/unit testing for the class "DamselRescuingKnight" and for any other better example class (without DI), to make me realize the point/stage at which DI makes unit testing easier ?
The difficulty in your above example comes when you try to test DamselRescuingKnight. Assume, you want to test that one (see below)
public class DamselRescuingKnight implements Knight {
private RescueDamselQuest quest;
public DamselRescuingKnight() {
this.quest = new RescueDamselQuest();
}
public void embarkOnQuest() {
quest.embark();
}
}
public class DamselRescuingKnightTest {
#Test
public void knightShouldEmbarkOnQuest() {
DamselRescuingKnight knight = new DamselRescuingKnight ();
knight.embarkOnQuest();
// now what?
}
}
how can you be sure that knight.embarkOnQuest() does actually do anything? The answer is that you can't because you can't access the quest instance it uses internally.
Now in order to be able to test such a class, you would add a getQuest() method to the Knight, and then also add a isEmbarked() method to Quest.
It is also quite fair to say, that this example is very simple, because the knight only calls the quest without parameters, and nothing else. If knight would interact with a quest and also get some weaponary from a Blacksmith, then you would also somehow need to allow access for that. You could probably do all the boilerplate to get that done. But then assume, you're passing parameters to blacksmith - how do you ensure that the passed parameters were correct? Or how do you ensure that the knight gets his/her weapon before going to the quest?
This is where dependency injection comes to the rescue. you can just create mocks (either by using a mock framework, or by implementing your own mocks) so that you can verify that your knight does the expected things.
The problem is of course the quest variable. You want to somehow check that the embark() method is invoked. Without being able to replace it with a mocked instance, this is very hard.
If the variable were protected instead of private, the test case could overwrite it by virtue of living in the same package.
You can also use Aspect-Oriented Programming to replace the variable.
But the easiest is if the code is written with dependency injection from the get-go.
You ask to see how AOP can be used. The following is an example of an AspectJ pointcut that you can use in a unit test to replace the RescueDamselQuest instance with a mocked one called MockRescueDamselQuest (apologies if I don't get the syntax exactly right, it has been a while since I used AspectJ):
aspect MockRescueDamselQuestInstantiations {
RescueDamselQuest around (): call(RescueDamselQuest.new()) {
return new MockRescueDamselQuest();
}
}
This will catch any instantiations of RescueDamselQuest (i.e. calls to new RescueDamselQuest()) and return a MockRescueDamselQuest object instead.
Given how much more wiring this requirest, I'd strongly suggest using dependency injection instead!
This perplexed me as well when I was reading this in Spring in Action. After reading above answers I wanted to add that when DI is not used then Junit method need to call method of object which is private (which is in accessible) and this object Quest is created in constructor of DamselRescuingKnight so test case for embarkQuest() can't be written. On contrary when using DI then you are externalizing object creation and Junit method can create that object so it will be accessible to it then can test emabarkQuest() which eventually need to test quest method
Is it possible to instantiate and assign a singleton to a reference with Guice before creating the Module and pass that instance to the Module constructor be bound during configuration?
Here is an example of what I mean:
I have a method that allows me to create objects depending on a custom implementation of an interface which is being passed in constructor as an Optional (if the user won't provide a custom implementation, we will use the default one), which is being done by binding the interface to that particular implementation in the Module class. :
public static MyClass createMyClassObject(Optional<SpecialInterface> customSpecialInterfaceObject) {
SpecialInterface specialInterfacebject;
if(customSpecialInterfaceObject.isPresent() {
specialInterfaceObject = customSpecialInterfaceObject.get()
} else {
/* here I would like to bind it to an instance of the DefaultSpecialInterfaceObject but can't really do something like:
Injector injector = Guice.createInjector(myClassModule);
DefaultSpecialInterface instance = injector.getInstance(DefaultSpecialInterface.class);
as the module is yet to be created */
}
MyClassModule myClassModule = new MyClassModule(specialInterfaceObject);
Injector injector = Guice.createInjector(myClassModule);
return injector.getInstance(MyClass.class);
}
I'm currently using classes instead of instances to solve this problem, such as in the example below, but I don't quite like this solution. Would be happy to see a better way of doing it:
private static Class resolveSpecialInterfaceObject(Optional<SpecialInterface> customSpecialInterfaceObject) {
Class specialInterfaceObjectClass;
if (customSpecialInterfaceObject.isPresent()) {
specialInterfaceObjectClass= customSpecialInterfaceObject.get().getClass();
} else {
specialInterfaceObjectClass = DefaultSpecialInterface.class;
}
return specialInterfaceObjectClass;
}
public abstract class MyClassModule extends AbstractModule {
private final Class<SpecialInterface> specialInterfaceObjectClass;
public MyClassModule(Class<SpecialInterface> specialInterfaceObjectClass) {
this.specialInterfaceObjectClass= specialIntefaceObjectClass;
}
#Override
protected void configure() {
bind(SpecialInterface.class).to(specialInterfaceObjectClass);
}
}
Edit, from a comment below:
one more thing- didn't want to make the question too long; actually, I also want to perform another operation on the resulting instance of SpecialInterface, but only if it is the instance of DefaultSpecialInterface and I don't think it should be done in the Module. I was thinking if I could just have this bean up and running before, such as in Spring, so I could just pass it to the Module, but also use it in another method call before?
Can you take the whole Optional and use bind(...).toInstance(...)?
public static MyClass createMyClassObject(
Optional<SpecialInterface> customSpecialInterfaceObject) {
MyClassModule myClassModule = new MyClassModule(customSpecialInterfaceObject);
Injector injector = Guice.createInjector(myClassModule);
MyClassFactory instance = injector.getInstance(MyClassFactory.class);
return instance.createMyClassObject();
}
class MyClassModule extends AbstractModule {
private final Optional<SpecialInterface> customObject;
MyClassModule(Optional<SpecialInterface> customObject) {
this.customObject = customObject;
}
#Override public void configure() {
if (customObject.isPresent()) {
// Singleton by necessity: Guice doesn't know how to create another one.
bind(SpecialInterface.class).toInstance(customObject.get());
} else {
// Default scoped. Add ".in(Singleton.class)" if necessary.
bind(SpecialInterface.class).toInstance(DefaultSpecialInterfaceClass.class);
}
}
}
If you want to perform additional initialization on DefaultSpecialInterface and nothing else, you have a number of options:
If some kind of initialization is important for all implementations and likely too heavy to put into a class constructor, add an initialize method on your SpecialInterface. Make the custom one a no-op, and implement it for DefaultSpecialInterface.
If the initialization is unique to DefaultSpecialInterface, I see no reason why it shouldn't be in the Module. Write a #Provides method or bind to a Provider<SpecialInterface> that creates and initializes DefaultSpecialInterface correctly.
If your real goal is to keep the business logic out of a Module, you can do so by extracting it into a free-standing Provider or DefaultSpecialInterfaceFactory that is responsible for that.
Remember, Guice is responsible for feeding fully-constructed objects into your object graph, and that means that injecting a SpecialInterface should get a ready-to-use implementor of the SpecialInterface general contract. If Guice needs to perform some initialization to make that happen, it's not unreasonable to have it do so, and a Module isn't a bad place to do it.
I have the following classes:
public class CacheModule extends AbstractModule {
#Override
protected void configure() {
bindConstant().annotatedWith(Names.named(TIMEOUT")).to(60);
// ...etc.
}
}
public class DefaultCacheAdaptor implements CacheAdaptor {
private CacheModule bootstrapper = new CacheModule();
#Named("TIMEOUT") private int timeout;
// other fields omitted for brevity
public DefaultCacheAdaptor() {
super();
Injector injector = Guice.createInjector(bootstrapper);
#Named("TIMEOUT") int t = injector.getInstance(Integer.class);
setTimeout(t);
}
}
public class QueueModule extennds AbstractModule {
#Override
public void configure() {
bind(CacheAdaptor.class).to(DefaultCacheAdaptor.class);
}
}
public class DefaultQueueAdaptor implements QueueAdaptor {
private QueueModule bootstrapper = new QueueModule();
private CacheAdaptor cacheAdaptor;
public DefaultQueueAdaptor() {
super();
Injector injector = Guice.createInjector(bootstrapper);
setCacheAdaptor(injector.getInstance(CacheAdaptor.class));
}
}
The CacheModule/CacheAdaptor/DefaultCacheAdaptor is located in a different JAR than QueueModule/QueueAdaptor/DefaultQueueAdaptor, and so the latter JAR depends on the former JAR at runtime (obviously).
The purpose of coding things this way is to allow the CacheModule to boostrap/inject the entire object graph under DefaultCacheAdaptor when the user writes:
CacheAdaptor cacheAdaptor = new DefaultCacheAdaptor();
Ditto for the QueueAdaptor.
It just so happens to be that the QueueAdaptor gets injected with a CacheAdaptor.
However, DefaultCacheAdaptor is the "root" of its own object tree, and should always be injected by the CacheModule.
So I ask: how can I bind DefaultCacheAdaptor to CacheAdaptor from inside QueueModule, but ensure that the DefaultCacheAdaptor is itself initialized/bootstrapped by the CacheModule?
To be honest it sounds like this problem isn't actually one of Guice, but instead the standard problem across software engineering: ensuring your dependencies do what they claim to do. QueueModule shouldn't concern itself about whether DefaultCacheAdaptor holds up to its general contract. Instead, write a unit test for DefaultCacheAdaptor that guarantees that it bootstraps itself, then use it in QueueModule without a second thought.
This is especially true because DefaultCacheAdaptor has a completely unrelated injector tree. You should be able to use DefaultCacheAdaptor opaquely, and stop concerning QueueAdaptor with its implementation details. Its bootstrapping is part of its implementation, not its API.
Even if you were to merge the two Injector graphs into one (by injecting the Injector and calling createChildInjector, for instance), there's very little way to guarantee at compile time that bindings you need in other modules will exist, because Modules work at runtime. Your best bet is to write a unit test. You can fail a little faster by calling requireBinding, which will fail at Injector creation if that particular dependency doesn't end up satisfied externally.
The more I read mock example, the more I get confused...
I have classA method eat() that calls FatDude class eatThemAll()
public class classA {
FatDude dude = new FatDude();
public String eat() {
String result = dude.eatThemAll();
}
}
public class FatDude {
public String eatThemAll() {
return "never full";
}
}
Now I want to test classA eat() method by mocking FatDude class.
public class MockFatDude extends FatDude {
//override
public String eatThemAll() {
return "very full";
}
}
------------- test --------------
public class DoTest {
public void runTest() {
classA cl = new ClassA();
String out = cl.eat();
assertEqual(out, "very full");
}
}
This DoTest runTest() won't use MockFatDude class of course. One way I can think is to change the code to pass FatDude to eat() method of ClassA like:
public class classA {
public String eat(FatDude dude) {
String result = dude.eatThemAll();
}
}
Then change my test method to:
public class DoTest {
public void runTest() {
classA cl = new ClassA();
String out = cl.eat(new MockFatDude());
assertEqual(out, "very full");
}
}
But as you can see, I had to change the source code to meet my need.
Is this the right way to do? What if I am not allowed to change my source code?
I know if I apply TDD concept, it is OK to change source code but I would like to hear
some opinion or advice if what I have shown above is right way to do.
Mocking and the Dependency Inversion Principle (DIP) go hand in hand, and in most languages, Mocks work best by decoupling classes by means of interfaces.
In your instance, this will work without you needing to change code: (Edit : I mean, in future, if you design your app this way, you won't need to change code to mock dependencies :))
Abstract an interface IDude
Concrete classes FatDude (and MockFatDude) should implement IDude interface
provide a mechanism for an IDude instance to be 'set' or injected into classA - Dependency Injection (constructor or get / sets); or Service Locator pattern work best (to replace a concrete classfactory)
Also note that many mocking frameworks actually allow you to build up the Mock concrete class 'on the fly' (see MoQ et al), so you can create the functionality of MockFatDude directly in your unit test.
Yes. You've stumbled on some good design directly because of your unit test. If you look more closely, you'll see that you removed the coupling between classA and FatDude. Now FatDude can be an interface for behavior that gets passed in when needed. ClassA doesn't need to know what kind of FatDude it's getting, or how to construct a FatDude (with cheeseburgers?).
Your solution is exactly what I would have done. There's nothing wrong with changing your code to accomodate TDD, as long as you understand the reasons and the benfits/drawbacks to making such changes.