5

I'm trying to write some tests for fragments which have fields annotated with @Inject. For example, a chunk of my app looks like this:

Module:

@Module public class PdfFactoryModule { @Provides @Singleton PdfFactory providePdfFactory() { return PdfFactory.getPdfFactory(); } } 

Component:

@Singleton @Component(modules = PdfFactoryModule.class) public interface CorePdfComponent { void inject(PagerFragment pagerFragment); } 

Application:

public class CorePdfApplication extends Application { @NonNull private CorePdfComponent component; @Override public void onCreate() { super.onCreate(); component = DaggerCorePdfComponent.builder().build(); } @NonNull public CorePdfComponent getComponent() { return component; } } 

PagerFragment:

public class PagerFragment extends Fragment { @Inject PdfFactory pdfFactory; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); //Dagger 2 ((CorePdfApplication) getActivity().getApplication()).getComponent().inject(this); } 

(Note that these are only snippets of my whole code, I'm showing only the essentials for this particular dependency to keep it clear.)


I was trying to do a test like this:

Fake Module:

@Module public class FakePdfFactoryModule extends PdfFactoryModule { @Override PdfFactory providePdfFactory() { return Mockito.mock(PdfFactory.class); } } 

Fake Component:

@Singleton @Component(modules = FakePdfFactoryModule.class) public interface FakeCorePdfComponent extends CorePdfComponent { void inject(PagerFragmentTest pagerFragmentTest); } 

Fake Application:

public class FakeCorePdfApplication extends CorePdfApplication { @NonNull private FakeCorePdfComponent component; @Override public void onCreate() { super.onCreate(); component = DaggerFakeCorePdfComponent.builder().build(); } @NonNull public FakeCorePdfComponent getComponent() { return component; } } 

Test:

@RunWith(RobolectricTestRunner.class) @Config(constants = BuildConfig.class, sdk = 21, application = FakeCorePdfApplication.class) public class PagerFragmentTest { PagerFragment pagerFragment; @Before public void setup() { pagerFragment = new PagerFragment(); startVisibleFragment(pagerFragment); } @Test public void exists() throws Exception { assertNotNull(pagerFragment); } 

But the DaggerFakeCorePdfComponent doesn't generate. I may have messed up big time because I never tested with dependency injection. What am I doing wrong?

5
  • If you're compiling with Dagger on the classpath, the failure to create DaggerFakeCorePdfComponent should come with an error, in your IDE's "Output" tab or your compiler's error log. Can you find any output like that? (Separately, I can't see where you're using Dagger in your test; why do you want the test accessible on the Component, as opposed to getting your system-under-test or dependency from a freestanding component?) Commented Sep 12, 2016 at 19:13
  • It just says Error:(14, 21) error: cannot find symbol variable DaggerFakeCorePdfComponent As for the tests I would like to test the fragment itself but it will not run without the dependencies. Commented Sep 12, 2016 at 20:19
  • A bit of a shot in the dark, but my guess is that robolectric is actually not running the correct gradle tasks to run the apt plugin and generate the classes for you. Have you tried adding testCompile <dagger-compiler> in addition to apt? If not can you give it a shot and let me know here pls. Commented Sep 13, 2016 at 7:32
  • My dependency looks like this: testCompile 'org.hamcrest:hamcrest-core:1.1' testCompile 'org.hamcrest:hamcrest-library:1.1' testCompile 'org.hamcrest:hamcrest-integration:1.1' testCompile "org.robolectric:robolectric:3.1.1" testCompile "org.robolectric:shadows-support-v4:3.1.1" compile 'com.google.dagger:dagger:2.6.1' apt "com.google.dagger:dagger-compiler:2.6.1" Do you want me to add testcompile "com.google.dagger:dagger-compiler:2.6.1" at the end? It gives me Error:(50, 0) Could not find method testcompile() for arguments [com.google.dagger:dagger-compiler:2.6.1] Commented Sep 13, 2016 at 9:10
  • I know you already accepted the answer, but it was suppose to be testCompile with capital C :) Commented Sep 14, 2016 at 10:31

2 Answers 2

10

My advice - "Do not use dagger in tests".

Just change your code to next:

public class FakeCorePdfApplication extends CorePdfApplication { @NonNull private CorePdfComponent component = mock(CorePdfComponent.class); @Override public void onCreate() { super.onCreate(); } @NonNull public CorePdfComponent getComponent() { return component; } } 

And:

@RunWith(RobolectricTestRunner.class) @Config(constants = BuildConfig.class, sdk = 21, application = FakeCorePdfApplication.class) public class PagerFragmentTest { PagerFragment pagerFragment; @Before public void setup() { pagerFragment = new PagerFragment(); CorePdfComponent component = ((CorePdfApplication)RuntimeEnvironment.application).getComponent(); doAnswer( new Answer() { Object answer(InvocationOnMock invocation) { fragment. pdfFactory = mock(PdfFactory.class); return null; } }).when(component).inject(pageFragment); startVisibleFragment(pagerFragment); } @Test public void exists() throws Exception { assertNotNull(pagerFragment); } } 
Sign up to request clarification or add additional context in comments.

3 Comments

Works now :) Thanks!
"Do no use Dagger in tests" is a bold statement
@Chisko True! I'm not a native speaker. My intention was to say - don't use Dagger in this type of tests
1

You may try:

androidTestApt "com.google.dagger:dagger-compiler:<version>" 

I was having similar problem, it worked for me.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.