I have created the following test class. The problem is that DaggerTestDiComponent is not being found - even though I can see it in the build directory.
I have looked through similar SO questions but they seem to concern older versions of gradle/Dagger2 and don't seem to apply (at least from what I can see). My app Dagger code is working OK.
public class TestMvpEngineeringPresenter {
@Mock
IMvpEngineeringView iMvpEngineeringView;
@Inject
MvpEngineeringPresenter mvpEngineeringPresenter;
@Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();
@Before
public void setUp() {
TestDiComponent component = DaggerTestDiComponent.builder()
.testAppModule(new TestAppModule()).build();
component.inject(this);
}
@Test
public void testStationControlSwitchChange() {
mvpEngineeringPresenter.assignEngineeringView(iMvpEngineeringView);
mvpEngineeringPresenter.onLoad();
mvpEngineeringPresenter.switchChanged(new SwitchChange(0, true));
assertEquals(true, mvpEngineeringPresenter.iStationModel.getStationControls().get(0).isOnOff());
mvpEngineeringPresenter.switchChanged(new SwitchChange(0, false));
assertEquals(false, mvpEngineeringPresenter.iStationModel.getStationControls().get(0).isOnOff());
}
}
My build.gradle file looks like this:
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion "25.0.0"
defaultConfig {
applicationId "com.fisincorporated.mvc_mvp_mvvm"
minSdkVersion 25
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
dataBinding {
enabled = true
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
// Android support stuff
compile 'com.android.support:design:25.0.1'
compile 'com.android.support:appcompat-v7:25.0.1'
compile 'com.android.support:recyclerview-v7:25.0.1'
// Butterknife - also includes library for Dagger
compile 'com.jakewharton:butterknife:8.4.0'
compile 'com.google.dagger:dagger:2.8'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0'
// For MVP Observer/Subscriber
compile 'io.reactivex:rxandroid:1.2.0'
compile 'io.reactivex:rxjava:1.1.5'
// For Dagger2
// compile 'com.google.dagger:dagger:2.8' // Added above for ButterKnife
annotationProcessor 'com.google.dagger:dagger-compiler:2.8'
// For testing
testCompile 'junit:junit:4.12'
// Mockito of course!
testCompile "org.mockito:mockito-core:2.+"
testAnnotationProcessor 'com.google.dagger:dagger-compiler:2.8'
}
Here's TestDiComponent
@Singleton
@Component(modules = {TestAppModule.class}) // comma separated list of classes
public interface TestDiComponent {
void inject(TestMvpEngineeringPresenter testMvpEngineeringPresenter);
}
Here is TestAppModule
@Module
public class TestAppModule {
@Provides
public IStationModel getStationModel() {
IStationModel iStationModel = Mockito.mock(IStationModel.class);
when(iStationModel.getStationName()).thenReturn("Mocked Station");
when(iStationModel.getStationControls().size()).thenReturn(2);
when(iStationModel.getBigButtonName()).thenReturn(("Log Button"));
when(iStationModel.getLogHint()).thenReturn("Enter log text here");
for (int i = 0; i < 2; ++i) {
when(iStationModel.getStationControls().get(i)).thenReturn(new StationControl("Test Switch" + i,false));
}
return iStationModel;
}
@Provides
public MvpEngineeringPresenter getMvpEngineeringPresenter() {
return new MvpEngineeringPresenter();
}
}
See this testing philosophy discussion for those downsides. It is generally recommended to create a Dagger component in your tests to instantiate objects, whether that is a larger test component for many tests or a small focused test component for the individual test.
Now, you can use DaggerApplicationComponent that was generated at compile-time for your ApplicationComponent interface. Show activity on this post. Maybe you forgot to annotate ModuleClass with @Module ? Show activity on this post.
Hilt allows your tests to easily access Dagger bindings, provide new bindings, or even replace bindings. Each test gets its own set of Hilt components so that you can easily customize bindings at a per-test level.
A Component in Dagger2 has methods named inject that receive the instance to get instances injected into it, not the other way around. In the code above the class AClassThatShouldGetInstancesInjected will typically call componentClass.inject (this); to get instances injected into itself.
Maybe you are locating the classes under your androidTest folder and you are not adding dagger-compile lib as androidTestCompileAnnotationProcessor
/ androidTestCompileAnnotationProcessor
to your gradle app file. That is not allowing dagger compiler to generate you DaggerXXX classes under your androidTest folder.
I tried to add comment on this but formatting was lousy so I will add as answer but it is somewhat incomplete.
Android Studio still says it can't find the generated DaggerTestDiComponent class, but my code does execute and the test runs.
For reference build.gradle:
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion "25.0.0"
defaultConfig {
applicationId "com.fisincorporated"
minSdkVersion 25
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
dataBinding {
enabled = true
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
// Android support stuff
compile 'com.android.support:design:25.0.1'
compile 'com.android.support:appcompat-v7:25.0.1'
compile 'com.android.support:recyclerview-v7:25.0.1'
// Butterknife - also includes library for Dagger
compile 'com.jakewharton:butterknife:8.4.0'
compile 'com.google.dagger:dagger:2.9'
provided 'javax.annotation:jsr250-api:1.0'
annotationProcessor('com.jakewharton:butterknife-compiler:8.4.0', {
exclude group: 'com.android.support',
module: 'support-annotations'
})
// For MVP Observer/Subscriber
compile 'io.reactivex:rxandroid:1.2.0'
compile 'io.reactivex:rxjava:1.1.5'
// For Dagger2
// compile 'com.google.dagger:dagger:2.8' // Added above for ButterKnife
annotationProcessor 'com.google.dagger:dagger-compiler:2.9'
// For testing
testCompile 'junit:junit:4.12'
// Mockito
testCompile 'org.mockito:mockito-core:2.4.0'
testAnnotationProcessor 'com.google.dagger:dagger-compiler:2.9'
//provided 'javax.annotation:jsr250-api:1.0'
// For Android/Mockito testing
androidTestCompile 'junit:junit:4.12'
androidTestCompile('com.android.support.test:runner:0.5', {
exclude group: 'com.android.support',
module: 'support-annotations'
})
androidTestCompile 'com.android.support.test:rules:0.5'
androidTestCompile 'org.mockito:mockito-core:2.+'
androidTestCompile 'com.google.dexmaker:dexmaker:1.2'
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2'
// Android espresso testing
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support',
module: 'support-annotations'
})
// androidTestCompile 'com.android.support.test:runner:0.5' added above
// following added to get past version conflict
androidTestCompile 'com.android.support:support-annotations:25.0.1'
}
I also modified my TestAppModule.getStationModel to not mock my StationModel class as I wasn't able to mock it the way I thought I could (I am just learning Mockito). So here that is:
@Module
public class TestAppModule {
@Provides
@Singleton
public IStationModel getStationModel() {
IStationModel iStationModel = StationModel.getStationModel();
return iStationModel;
}
@Provides
public MvpEngineeringPresenter getMvpEngineeringPresenter(IStationModel istationModel) {
return new MvpEngineeringPresenter(istationModel);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With