GWT google-gin field injection not working - java

I'm trying to get field injecting to work in google-gin, but when I call TestClass.test() the injected field is null. What am I doing wrong? According to the docs field injection should be really straight forward. Is there anything I'm missing in the ContextModule class?
public class MainEntry implements EntryPoint {
private final ContextInjector injector = GWT.create(ContextInjector.class);
#Override
public void onModuleLoad() {
injector.getAppMain();
}
}
#GinModules(ContextModule.class)
public interface ContextInjector extends Ginjector {
AppMain getAppMain();
}
public class MyLogger {
}
public class ContextModule extends AbstractGinModule {
#Override
protected void configure() {
bind(MyLogger.class).in(Singleton.class);
}
}
public class AppMain {
#Inject
AppMain(MyLogger logger) {
// logger is injected properly here
new TestClass().test();
}
}
public class TestClass {
#Inject
private MyLogger logger;
public void test() {
// logger is null here!
}
}

Your TestClass is not managed by GIN, so GIN won't inject anything in it. You have to either let GIN instantiate TestClass (e.g. change MyLogger to TestClass in your AppMain constructor, and call test() on the given instance), or ask GIN to inject an existing TestClass instance's members (add a method to your Ginjector that takes a TestClass as argument, when called, it'll inject fields and methods of the passed-in instance).

Related

Mocked static outer class members are null when testing static inner class with PowerMockito

I have a class that looks like this:
public class OuterClass {
protected static Server s;
public static class CrazyEvent implements Runnable {
#Override
public void run() {
s.getSystemInfo();
}
}
}
It has a static member s of type Server, and an inner static class called CrazyEvent which extracts some info from the Server.
I'm trying to test this run() method in powermockito:
#RunWith(PowerMockRunner.class)
#PrepareForTest(OuterClass.class)
public class StaticInnerClassTest {
private static class ServerMock extends Server {
protected ServerMock(ServerConfig sc) {
super(sc);
}
#Override
public void start() {
}
}
private static class ServerConfigMock extends ServerConfig {
}
#Mock
ServerMock s = new ServerMock(new ServerConfigMock());
#Mock
UserMan um;
#InjectMocks
OuterClass.CrazyEvent ce = new OuterClass.CrazyEvent();
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(s.getUserMan()).thenReturn(um);
}
#Test
public void testInnerClass() {
ce.run();
}
}
Let's walk through the code:
I'm extending the actual Server object with ServerMock so I can override an annoying method that gets called in the constructor. My mocked Server object is s. Ideally, I'd like to inject this mock into the nested static inner class because it has to use it.
The problem is, when I call ce.run(), s is null and the mock is not properly injected. I'm pretty new to PowerMockito, and I've been struggling to find information on SO about this specific case.
Edit:
There's a private static slf4j logger in the outer class that is null when called by the run() method in the inner class. I don't know how to instantiate it. I tried extending the outer class and making the logger protected and instantiating it that way but no luck.
Nevermind, I accidentally left in a call to PowerMockito.mockStatic() which was breaking everything 
Just needed to add OuterClass.s = s in the setUp().
I also introduced an issue where I used PowerMockito.mockStatic(Outerclass.class) which was causing my static logger to become null. I removed this line.

Test class which depends on Guice Provider<T>

How to test a class which depends on Provider<>?
Please see the code below.
class ToTest {
#Inject
Provider<Processor> processorProvider;
public buildData() {
processorProvider.get().process();
}
class ProcessorProviderImpl implements Provider<Processor> {
#Inject
private Handler someHandler;
public Processor get() {
return new MyProcessor(somehandler)
}
}
public static class TestModule extends JukitoModule {
#Override
protected void configureTest() {
bind(Processor.class).toProvider(
ProcessorInstanceProviderImpl.class);
bindMock(SubHandler.class).in(TestSingleton.class);
}
}
class Handler {
#Inject
private SubHandler subHandler; // this is singleton instance
}
}
So when I mock subHandler it doesn't work and when I run unit test I am getting a NullPointerException where subHandler.handle() is getting called.
You can use Providers.of() to initialize processorProvider with a provider of your collaborator instance.
https://google.github.io/guice/api-docs/latest/javadoc/index.html?com/google/inject/util/Providers.html
test = new ToTest();
test.processorProvider = Providers.of(processorMock);

Inject a TypeListener

I have this scenario where I want to inject a TypeListener with dependencies, but it will never work because the TypeListener is used to actually perform the injection.
How can I get this thing done? Is there a guicey-way?
Notes:
I'm using Guice 4.0
MyManager will be used after Guice::createInjector.
Both MyManager::registerType and MyManager::use are called exclusively before Guice::createInjector returns.
MyDependency is present to show that MyManager cannot be instanciated with new. I will also be used after Guice::createInjector has returned.
I created the following SSCCE to showcase my issue:
import com.google.inject.*;
import com.google.inject.matcher.*;
import com.google.inject.spi.*;
public class MyClass {
public static void main(String[] args) {
Guice.createInjector(new MyModule());
}
static class MyModule extends AbstractModule {
#Override protected void configure() {
TypeListener listener = new MyTypeListener();
requestInjection(listener);
bindListener(Matchers.any(), listener);
}
}
static class MyTypeListener implements TypeListener {
#Inject MyManager manager;
#Override public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
Class<?> rawType = type.getRawType();
manager.registerType(rawType);
encounter.register(new InjectionListener<I>() {
#Override public void afterInjection(I injectee) {
manager.use(rawType, injectee);
}
});
}
}
#Singleton static class MyManager {
#Inject MyManager(MyDependency dependency) { }
void registerType(Class<?> type) { }
void use(Class<?> type, Object injectee) { }
}
static class MyDependency { }
}
I think at least some of the time (in tests or code analysis) type listeners have no cohesion to the types they are listening to, so there's no reason to have one injector. You'd use one injector to create the listener and one injector to create the code to be tested/analyzed.
If you really want one injector (e.g. if the types in the injector you wish to listen to and the types needed by the listener are cohesive) then your best bet is AbstractModule's getProvider() method. So, if MyTypeListener needs an instance of Foo, this is what MyModule would look like:
static class MyModule extends AbstractModule {
#Override protected void configure() {
TypeListener listener = new MyTypeListener(getProvider(Foo.class));
bindListener(Matchers.any(), listener);
}
}
If you haven't used getProvider(), be forewarned that you cannot call .get() on the provider until the injector is constructed. As long as you don't call it from the context of the listener's constructor you should be fine.

Does method injection with Guice work if constructor is not injected?

I have a class where I need to inject a variable but the constructor is not guice injected.
public class Foo{
private boolean x;
public Foo(){
//sets some variables
}
#Inject
public void setX(boolean x){
this.x=x;
}
}
The value of x is not getting injected. Is it necessary to use injection in constructor for guice to recognize method injection?
Do I need to call this method from some other class for this to work?
Thanx in advance
If you're going to use Guice to #Inject Foo then Guice needs to create the object - either from the injector or from another #Inject point in separate class. Guice can't help you inject objects that it didn't create.
In this case it's not necessary to add #Inject to the constructor because Guice can automatically inject a no argument constructor. For example:
public class MethodInjectionTest {
static class Foo {
private boolean x;
public Foo(){
//sets some variables
}
#Inject
public void setX(boolean x){
this.x=x;
}
}
Injector i = Guice.createInjector(new AbstractModule() {
protected void configure() {
bind(Boolean.class).toInstance(Boolean.TRUE);
}
});
#Test
public void methodInjection() {
Foo foo = i.getInstance(Foo.class);
assertThat(foo.x, is(true));
}
// EDIT: An example based on the comment by #JeffBowman
#Test
public void memberInjection() {
Foo foo = new Foo();
i.injectMembers(foo);
assertThat(foo.x, is(true));
}
}
If your real world class has a need to mix Guice controlled dependencies with client provided dependencies during construction have a look at assisted inject

Google Guice - Use generic as parameter of injected field

I want to use a generic parameter of a class for a field that is injected, but guice complains about a unbound key. Is it possible to inject the field in Test2?
Example:
public static class Test1<T1> {
}
public static class Test2<T2> {
#Inject
public Test1<T2> test;
}
public static void main(String[] args) throws Exception {
Injector injector = Jsr250.createInjector(Stage.PRODUCTION, new TestModule());
Test2<String> test = injector.getInstance(Key.get(new TypeLiteral<Test2<String>>(){}));
}
private static class TestModule extends AbstractModule {
#Override
protected void configure() {
bind(new TypeLiteral<Test1<String>>(){}).toInstance(new Test1<String>());
bind(new TypeLiteral<Test2<String>>(){}).toInstance(new Test2<String>());
}
}
Well, this is overkill for java generics. You code would not work even without injection, cuz Test1<T2> cannot match Test1<String>. You should consider different approach, try to use Annotation binding like:
public static class Test2 {
#Inject #Named("T2")
public Test1<someGenericInterface> test;
}
bind(new TypeLiteral<Test1<someGenericInterface>>(){}).annotatedWith(Names.named("T2")).toInstance(new Test1<T2>()); //T2 implements someGenericInterface
bind(new TypeLiteral<Test1<someGenericInterface>>(){}).annotatedWith(Names.named("T1")).toInstance(new Test1<T1>()); //T1 implements someGenericInterface
or implement specific Provider Provider bindings or use MapBinder

Categories