Guice field injection - java

So here's the thing. I'm trying to inject some fields with guice, but it turns out that they are always null (not trying to use them on the constructor).
public class A {
#Inject
private SomeClass bar;
public A() {
foo();
}
public someMethod() {
bar.doSth();
}
}
public class B {
private A a;
public B() {
a = new A();
}
public someOtherMethod() {
a.someMethod();
}
}
Now whenever the app executed someOtherMethod and a tries to run bar.doSth a nice NullPointerException is raised.
So in order to fix this i ended Injecting the field manually inside the constructor:
public A() {
final Injector injector = Guice.createInjector();
bar = injector.getInstance(SomeClass.class);
}
But this is ugly, unclear, has a lot of boilerplate and I'm forced to do it on many places which make it tedious.
Is there any other way to archive this? Or an explanation of why the field is not being injected?
Thanks
Note:
I'm currently unavailable to do the propper injection on the constructor (with bar as a parameter) because of the refactoring it would imply. The project is now under heavy production and thus this kind of refactoring can't be done right now.

The IOC container only controls what you tell it to control. It doesn't know about the A inside of B, because it's being constructed directly, not managed by the container. You need to inject the A as well:
public class B {
#inject private A a;
public B() {}
...
}
And you can't just call new B() either, you need to inject the B as well.

Related

Different ways of mocking object creation in Mockito?

I see a couple different ways of mocking objects. What exactly are the differences between this approache using InjectMocks and the approach shown here: https://github.com/mockito/mockito/wiki/Mocking-Object-Creation?
#ExtendWith(MockitoExtension.class)
public class MyTest() {
#Mock ClassB uut;
#InjectMocks ClassA cA;
#Test
public TestOne() {
...
}
}
where
public class ClassA() {
public ClassA() {
ClassB temp = new ClassB();
}
}
versus the method shown here:
https://github.com/mockito/mockito/wiki/Mocking-Object-Creation
What exactly is the difference?
I believe there is no essential difference between those approaches.
InjectMocks approach
Actually for it to work, your class should accept the dependencies through the constructor or setters (and it never works with both). I would say that this approach makes the testing easier because you inject whatever you want to your class object at the initialization phase.
class Foo {
private final Bar bar;
public Foo(final Bar bar) {
this.bar = bar;
}
}
If this is our class under test, then all #InjectMock does is to create mocks, and do the following:
Foo foo = new Foo(barMock);
Apart from being testable, imagine if the Bar is an interface, then you can possibly you can switch between multiple implementations of it without actually touching the class code (ideally). If you have a DI framework, that's even easier. So, basically this format of the class makes it flexible.
Using one-line methods for object creation
Let's say this is our class under test. As you can see, I am initializing the property inside the constructor. Legally, with no reflection magic, I cannot put a mock bar variable neither during initialization nor after that.
class Foo {
private final Bar bar;
public Foo() {
this.bar = new Bar();
}
}
The reason that Mockito docs tell you to switch to either a one-liner method or a Factory helper is that:
Mockito cannot mock constructors, which means you cannot put a mock object in the place of bar without reflection, and you can only do that after the initialization. Generally, to point of my view on testing, reflection should be avoided as much as possible.
One-liner functions are looking as clean as constructors and they can be descriptive (like static factory methods).
So, when you switch your class to look like this:
class Foo {
private final Bar bar;
public Foo() {
this.bar = makeBar();
}
Bar makeBar() {
return new Bar();
}
}
Now, you can put a spy, and just mock the makeBar method easily. The same applies to the factory method as well. To be honest, the factory approach looks a bit wordy to me, but still, I am sure there will be times when it may come handy.

Inject instance in all objects using Guice

class A {
public A() {
}
}
class B {
#Inject
#Named("A")
private A a;
public B() {
}
public A getA() {
return a;
}
}
class AModule extends AbstractModule {
#Override
protected void configure() {
}
#Provides
#Singleton
#Named("A")
public A providesA() {
return new A();
}
}
We are doing like this:
AModule module = new AModule();
Injector injector = Guice.createInjector(module);
B b = injector.getInstance(B.class);
System.out.println(sample.getA());
But we have many classes with A as dependency and we don't want to add this code every time we create an instance.
So, is there any way to auto inject instance of A while creating instance of B?
It is (usually) not correct to create as many top-level Injectors as you suggest in your question. Injector creation is expensive, and once Guice has calculated your graph of dependencies, you should not need to calculate it all over again. In general there should be one top-level Injector across your application, and any other Injectors are either "child injectors" or parts of a separate and unrelated object graph.
In order from "worst" to "best":
Keep the Injector statically
If you are introducing DI into a lot of existing or legacy code, then it may be tempting to stash the Injector into a publicly-accessible object.
public class InjectorHolder() {
private InjectorHolder() {} // Not instantiable
private static Injector injector;
public static void initializeInjector() {
injector = Guice.createInjector(new AModule(), new BModule(), andSoOn());
}
public static Injector get() {
return injector;
}
public static B getB() {
return injector.getInstance(B.class);
}
}
At this point you can call InjectorHolder.get().getInstance(B.class) or InjectorHolder.getB() from the parts of the app you've migrated so far. Note that this may be difficult to test, and relies on Guice directly from across your application—both of which are not ideal.
Use Guice static injections
Guice provides a few features for static injection, notably the method call requestStaticInjection(Class... types). With a call to that in your module, Guice will inject static members that have #Inject annotations as soon as the Injector is created.
public class StaticBModule extends AbstractModule() {
#Override public void configure() { requestStaticInjection(BFactory.class); }
}
public class BFactory() {
#Inject #Named("B") private static Provider<B> bProvider;
public B get() {
return bProvider.get();
}
}
Now you can call new BFactory().get() instead of new B(), and it'll all go to the same injector. Naturally, you could also allow new B() instead if you put a static Provider<A> into your B class and request static injection for that instead, or you could keep your BFactory as an instance and replace it during tests to issue the B instances you need. At that point, you might as well just retrofit the classes that call new BFactory() to instead include a static Provider<B>, and have them inject statically, and then migrate those, all the way up until you have a full DI solution (explained below).
You may also consult this SO question, which has an example.
Ideal solution
You've shown us A and B, but presumably some other class C uses many instances of B, and maybe YourApplication (which contains your static main method) uses C. You can use Guice to create an instance of YourApplication or C, and then C can contain an injected Provider<B> bFactory. Then, rather than call new B(), you can call bFactory.get() to create as many B instances as you might need.
This way, your classes depend on exactly what they depend on, with no static state or references to Guice other than at the top level.

Mocking autowired field in the method

I was wondering whether there's a way to mock the field which is being autowired.
Consider the following case.
I have a class name A
public class A {
#Autowired
private B b;
public void aMethod() {
b.method();
}
}
The other class B looks like this
public class B {
public void method() {
// some code
}
}
Now i want to write junit for the method.
I know there's a way to mock the autowired field like this.
public class TestA {
#InjectMock
private A a;
#Mock
private B b;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
public void testAMethod() {
// write test case.
}
}
But my question is -> Is there a way to mock the autowired field inside method after creating object with new.
eg
public class TestA {
public void testAMethod() {
A a =new A();
// how to mock the B instance in it.
}
}
Please suggest or there's no way to do this????
I dont want to change from private modifier. Nor i want to add getter's and setters or reflection. I just want to know is there a way to mock the B instance after creating the new object of A class.
How about ReflectionTestUtils?
A a = new A();
B b = mock(B.class);
ReflectionTestUtils.setField(a, "b", b);
It's still reflection-based and has all related drawbacks, though it's quite simple and easy to read.
You can not do that with mockito, this would require to modify the bytecode of the class being tested. However Powermock allows such stubs. Note though that I and the creator of Powermock - Johan Haleby - would push for a refactoring instead of using Powermock. Powermock is very powerful, maybe too much, and working allows anyone to write legacy code, that would be difficultly maintainable or extensible (property you can find in poorly designed legacy code).
In your case I don't know what's wrong in your case with the dependency injection. However if the code need a new instance of B, it may be useful to have inject in A a factory/provider/builder class which will make a new instance of B. Such code can be easily stubbed with Mockito.

Mocking EJB injection in tests

Whenever I want to test a class which uses resource injection I end up including a constructor that will only be used within the test:
public class A {
#EJB
B b;
// Used in tests to inject EJB mock
protected A(B b) {
this.b = b;
}
public A() {}
// Method that I wish to test
public void foo() {
b.bar();
}
}
Is there another way of mocking resource injection or this is the correct pattern to follow?
you could use easy gloss to that effect, it mocks the EJBs injection system.
another way is to set the field using reflexion in your tests, I sometime use something like this :
public static void setPrivateField(Class<? extends Object> instanceFieldClass, Object instance, String fieldName, Object fieldValue) throws Exception {
Field setId = instanceFieldClass.getDeclaredField(fieldName);
setId.setAccessible(true);
setId.set(instance, fieldValue);
}
Eliocs,
If type B where an interface then you wouldn't "just" bo doing it for test-cases; you'd be allowing for any alternative implementations of "B's behaviour", even if the need for it/them hasn't been dreamed-up yet.
Yeah, basically that's the only pattern to follow (AFAIK)... so (rightly or wrongly) you may as well make the best of it ;-)
Cheers. Keith.
It's certainly one way to do it, although I'd rely on package access; don't provide a constructor injection point, but simply have your test in the same package as the bean being tested. That way, your test can just access the value directly (assuming it's not private):
#Test
public void EJBInjectionTest() {
A a=new A();
a.b=new B() {
// mock functionality here, of course...
};
assertNotNull(a.b);
}
According to this article (Mockito and Dependency Injection), Mockito has support for injecting mocked resources.
public class ATest
{
#InjectMocks
private A a; //this is your class under test into which the mocks will be injected.
#Mock
private B b; //this is the EJB to be injected.
#Before
public void setUp()
{
MockitoAnnotations.initMocks(this);
}
}
You can also inject multiple mocks. Just declare them in the same way as we did for B b.
The initMocks part can also be done in each test or in a BeforeClass setup method depending on your needs.

Is Spring able to handle this user case? Neither property nor constructor injection

Basically, I have a class A which depends on class B which in turn depends on a spring managed bean C, but I dont want to keep B as a class variable just use B inside one method for some reason. My solution is to create a static method get() in B which returns a instance of B. Now the problem is, C is not injected to B correctly.
// A cannot have B as a class/field variable.
public class A {
public void method(){
// B.get() returns a instance of B, but this instance is not the
// instance that spring created, it is the static "instance" in B.
B.get().doSomething();// ofcourse it throws out a nullpointer exception
}
}
class B{
#Resource(name = "c")
private C c;
private static B instance;
public static B get() {
return instance==null ? (instance=new B()) : instance;
}
public void doSomething(){
c.toString(); // this line will break if c is not
// injected to the instance of b
}
}
#Service("c")
class C {
}
How do I solve this problem??
The whole point of using Spring is it is a dependency injection framework, and you are hardcoding the dependency of B in A.
Try very hard not to do that. If you don't want to store B in an instance variable, pass it as an argument to the method.
If you are stubborn about doing that then you have to get an ApplicationContext and load it yourself. An alternative might be to have B implement InitializingBean and then have your afterPropertiesSet method register the current instance with a static instance variable.
There isn't a direct bit of spring to support this, but are are a couple of work arounds to solve the problem.
grab hold of the ApplicationContext in B.get() and call getBean in order to get spring to construct B. Getting hold of the ApplicationContext is another mission as it is typically not held anywhere statically, have a look in the spring reference manual for 'dirty singleton'
Let spring construct the bean and then keep a reference to it in the instance variable:
#Service('b')
class B{
#Resource(name = "c")
private C c;
private static B instance;
public B(){
// sets the static here
// not ideal...should use afterProperties set or what ever the Annotation equivalent is
instance = this;
}
public static B get() {
if( instance == null ){
throw new IllegalStateException("errr...say something useful here")
}
return instance;
}
public void doSomething(){
c.toString(); // this line will break if c is not
// injected to the instance of b
}
}
I've seen 2. used a couple of times on various projects, it's not pretty and if you have a choice don't do it, just get spring to wire the whole app. But if you don't have a choice, it might be the least worst option.
You'll have to get the bean programmatically from the Spring ApplicationContext, either within A#method(), or in the constructor of A or its initialization method, and caching the Spring injected B instance.

Categories

Resources