E. Fernandes
E. Fernandes

Reputation: 4017

Dagger2 + Mockito: How to Unit Test this scenario?

I'm working on a team project which has a very coupled code. I'm trying to increase the unit test coverage and I've faced the following scenario:

class Foo {
    static void methodA () {
        Bar b = new Bar();
        b.getContent();
    }
}

class Bar {

    @Inject
    DBAcessor mDBAcessor;

    Bar () {
        Dagger2.getInjector().inject(this);
    }

    public Object getContent() {
        mDBAcessor.fetchData();
    }

}

I want to unit test methodA(), however I don't know if it is possible to do it without passing the DBAcessor object via constructor to Bar() class. Bar should be a POJO model being widely used throughout the project, hence, I don't know if it would be a good idea to change its constructor and impact so many other classes. Any tips on how should I approach this scenario?

Upvotes: 0

Views: 1149

Answers (1)

R. Zagórski
R. Zagórski

Reputation: 20268

That is wrong design.

Whenever you have an access to the constructor, pass class dependencies into constructor. That really eases unit testing. Class Bar should look:

class Bar() {

    @Inject DBAcessor mDBAcessor;

    Bar (DBAcessor dbAcessor) {
        this.mDBAcessor = dbAcessor;
    }

    public Object getContent() {
        mDBAcessor.fetchData();
    }
}

Dagger2 methods declared in Component should only be used inside object you don't have an access to the constructor (Activity or Fragment).

Then nothing prevents you from doing that:

DBAccessor dbAccessor = Mockito.mock(DBAccessor.class);
Bar bar = new Bar(dbAccessor);
bar.getContent();
verify(bar, times(1)).fetchData();

If you really need to stick to such design, then you can't make unit tests on such object, as Dagger2 depends on Application object, which needs Context, which you cannot emulate in unit tests. Write your test as androidTest, create appropriate Activity, fetch Bar object from it and test it.

Upvotes: 1

Related Questions