Guy Chauliac
Guy Chauliac

Reputation: 650

simple dagger unit test fails

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?

Upvotes: 0

Views: 830

Answers (2)

mrlem
mrlem

Reputation: 474

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.

Upvotes: 1

ilkinulas
ilkinulas

Reputation: 3675

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();
    }
}

Upvotes: 0

Related Questions