0

I'm new to dagger. I created a very simply unit test to try to understand how I should use dagger. Unfortunately it fails. I've probably not understood some basic principles of dagger.

public class A {
    @Inject
    public B b;

    public B getB() {
      return b;
    }
}

public class B {
}

@Module(injects = { A.class, B.class })
public class DaggerModule {
    @Provides
    public A provideA() {
        return new A();
    }

    @Provides
    public B provideB() {
         return new B();
    }
}

and my test class which fails

public class DaggerTest extends TestCase {
    public void testDagger() {
        ObjectGraph theGraph = ObjectGraph.create(new DaggerModule());
        A theA = theGraph.get(A.class);
        assertNotNull(theA.getB());
    }
}

I thought that dagger would inject B into A since A wants it to be injected and DaggerModule contains a @Provides annotated method which creates B.

Update:

I found that when I write the module class like this

@Module(injects = { A.class })
public class DaggerModule {
    @Provides
    public B provideB() {
        return new B();
    }
}

the injection of B into A works. However I do not understand why it is not working when the module has a Provides annotated method which construct an instance of A. In that case the only way to get the injection to work is to actually write the injection yourself like:

@Module(injects = { A.class, B.class })
public class DaggerModule {
    @Provides
    public A provideA(B b) {
        A theA =  new A();
        theA.b = b;
        return theA;
    }

    @Provides
    public B provideB() {
         return new B();
    }
}

or to create a constructor in A which accepts B so that you can write

@Module(injects = { A.class, B.class })
public class DaggerModule {
    @Provides
    public A provideA(B b) {
        return new A(b);
    }

    @Provides
    public B provideB() {
         return new B();
    }
}

This need for having a constructor or setter in A which accepts B was just the kind of overhead I thought could by avoided by using Dagger.

So I'm I doing something wrong or did I misinterpreted the capabilities of dagger?

Wojciech Wirzbicki
  • 3,887
  • 6
  • 36
  • 59
Guy Chauliac
  • 640
  • 7
  • 8

2 Answers2

1

I noticed exactly the same behaviour, i.e. @Provides produced instances don't get their @Inject marked members injected. cf Dagger & nested injections

I did exactly the same as you: use @Provides parameters injection to forward to the constructor (without the same impression that it kind of defeats dagger's purpose). I'll try to dive a bit more into dagger to figure out if this is a normal behaviour as soon I have some spare time.

Community
  • 1
  • 1
mrlem
  • 475
  • 4
  • 11
0

If you make Class A the entry point of your module than dagger will inject dependecy B to A.

@Module(entryPoints = { A.class })
public class DaggerModule {
    @Provides
    public A provideA() {
        return new A();
    }

    @Provides
    public B provideB() {
         return new B();
    }
}
ilkinulas
  • 3,515
  • 3
  • 22
  • 29
  • It seems like 'entryPoints' has been renamed to 'injects' since version 1.0.0. so I've written '@Module(injects = { A.class })' But still B is not injected into A. – Guy Chauliac May 12 '13 at 05:27
  • According to your sample code you do not need to set B as "injects". Did you tried constructor injection? – ilkinulas May 12 '13 at 06:03