I'm new in writing android unit tests and faced with a problem of injecting some mock dependencies into my test class. I found a lot of articles how I can do it using "old" Dagger (version < 2.10), but nothing about Dagger with version > 2.10. I just want to write smth like that
#RunWith(JUnit4.class)
public class ConfigurationUnitTest {
#Inject SomeDependency someDependency;
public ConfigurationUnitTest() {
}
#Test
public void test() {
//use someDependency variable here
}
}
But I didn't find any way to inject some dependencies into this Test class. Hope someone helps me. Thanks.
Related
I have a testclass where I am running Mockito tests, like:
public class ViewModelTest {
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
public void openQuestion() {
viewModel.openQuestion(context, QUESTION_ID);
verify(questionRouter).open(context, QUESTION_ID); //just an example
}
}
Everything is working as should. However, I have to mock a static method in one of my test classes, so I add PowerMock to my class:
#RunWith(PowerMockRunner.class)
#PrepareForTest(Uri.class)
public class ViewModelTest { ...
and dependencies:
testImplementation 'org.powermock:powermock-core:2.0.2'
testImplementation 'org.powermock:powermock-api-mockito2:2.0.2'
testImplementation 'org.powermock:powermock-module-junit4-rule-agent:2.0.2'
testImplementation 'org.powermock:powermock-module-junit4-rule:2.0.2'
testImplementation 'org.powermock:powermock-module-junit4:2.0.2'
But when I now try to run the tests (let's say I have 15 test methods) I get NPE on most test methods:
java.lang.NullPointerException
at com.example.Viewmodel.prepare(StartViewModel.java:126)
I get NPE even in the method where I try to mock the static method:
PowerMockito.mockStatic(Uri.class);
PowerMockito.when(Uri.parse(anyString())).thenReturn(otherUri);
Before you downvote&vote to close for NPE, I have really looked at most answers in SO and other sites, tried many of them which of none worked for me. I followed tutorials for Powermock but I still get this errors, and I do not understand why. This is my last resort to try to solve this.
you are doing the test with the right way, just replace
PowerMockito.when(Uri.parse(anyString())).thenReturn(otherUri);
with when of Mockito
Mockito.when(Uri.parse(anyString())).thenReturn(otherUri);
and add this file https://gist.github.com/badr-ghazouan/1edbed170ce968ef0011f2721911ffc6 to the resource folder under test folder, mockito will load it automatically without doing anything.
Hope this works for you
I have a homemade library that generates DataMapper classes.
They are generated with #Singleton and #Inject annotations to be able to inject them where i need them.
But where it doesn't work is when Dagger tries to create the dependency tree, this error shows :
:data:kaptGenerateStubsDebugKotlin
e: /Users/me/myproject/data/build/tmp/kapt3/stubs/debug/com/myproject/data/di/DataComponent.java:11: error: [Dagger/MissingBinding] error.NonExistentClass cannot be provided without an #Inject constructor or an #Provides-annotated method.
public abstract com.myproject.domain.repository.ContentRepository contentRepository();
^
error.NonExistentClass is injected at
com.myproject.data.repository.ContentDataRepository.<init>(…, myGeneratedDataMapper, …)
com.myproject.data.repository.ContentDataRepository is injected at
com.myproject.data.di.module.DataModule.contentRepository(contentDataRepository)
com.myproject.domain.repository.ContentRepository is provided at
com.myproject.data.di.DataComponent.contentRepository()
:data:kaptDebugKotlin
:data:kaptDebugKotlin FAILED
Involved classes are :
DataModule (module for dagger)
#Module
class DataModule {
#Provides
#Singleton
fun contentRepository(contentDataRepository: ContentDataRepository): ContentRepository = contentDataRepository
}
DataComponent (component for dagger):
#Singleton
#Component(modules = [DataModule::class])
interface DataComponent {
fun contentRepository(): ContentRepository
}
ContentDataRepository
#Singleton
class ContentDataRepository #Inject constructor(
private val myGeneratedDataMapper: MyGeneratedDataMapper
) : ContentRepository {
...
}
MyGeneratedDataMapper
#Singleton
class MyGeneratedDataMapper #Inject constructor() {
...
}
The thing is, if i disable kapt of dagger dependency in gradle.build, then build, then enable it, then build, it works.
If i do a clean + build, it doesn't work, same error.
I want to make it work in one row.
I don't know if you are using AS3.2 or AS3.3 with androidX artifacts or not but Maybe this is the case with you too.
so when i migrated to androidX artifacts in AS3.2 i got hit with bunch of NonExistentClass errors ends the build with
kaptGenerateStubsDebugKotlin
:data:kaptDebugKotlin
:data:kaptDebugKotlin
I finally found out that it has something to do with Dagger itself and degraded the version from 2.17 to 2.16 now the latest version of Dagger2 is 2.18 which i can't use due to this bug / feature [they forgot about].
Update:
i found the solution and it just came today so here is the issue tracker link:
https://issuetracker.google.com/issues/115738511
so the bug was not in the Dagger but it was with Jetifier and i totally ignored the fact that it was set enabled during migration
here's the solution i copied from the link:
Sorry jetifier beta01 was not binary compatible with alpha10.
We have published beta02 that should fix this issue.
Please try:
buildscript { dependencies {
classpath 'com.android.tools.build.jetifier:jetifier-processor:1.0.0-beta02' } }
You're probably not going to like my answer but the order is kinda random.
Look at this thread for some more explaining and maybe some more guidance but, if you want to verify you are running first look at Gradle plugins and how to use them
I have a problem with Mockito. I have written tests for my presentation layer. I used mockito to mock some dependencies. Everything was working fin for last 2 months and suddenly I started receiving an exception:
java.lang.NoClassDefFoundError: Landroid/content/SharedPreferences;
Previously there were no problem with it at all. I have not changed the version of Mockito and JUnit in my gradle and it looks like:
testCompile "org.mockito:mockito-core:2.+"
testCompile 'junit:junit:4.12'
And my test class looks like:
#RunWith(MockitoJUnitRunner.class)
public class PostDetailsPresenterTest {
#Mock
SharedPreferences preferences;
#Before
public void setUp() {
SharedPrefsUtils utils = new SharedPrefsUtils(preferences);
}
}
But after starting tests I keep receiving an exception. Does someone had similar problem and know how to deal with it?
Try to clean and rebuild. Then ./gradlew clean test. If that doesn't help, remove the .gradle folder from your project and rebuild.
I am using Dagger 2 and would like to use it to inject different dependencies for different build flavours in Android Studio.
public class DemoApplication extends Application{
AppComponent component;
#Override
public void onCreate() {
super.onCreate();
component = DaggerAppComponent.builder().module(new Module()).build();
}
}
#Module
public class Module {
#Provides
#Singleton
public ClassA provideClassA(){
return new ClassA();
}
}
#Component (modules = {Module.class})
public interface AppComponent {
ClassA getClassA();
}
Now lets say I want object of ClassA to be returned for prod flavour but an object of ClassB (which extends from ClassA) in the debug flavour.
Use flavor-specific source sets
For example, let's consider mock and production flavors. Create mock and production directories and put them alongside main, place a separate class named Module in both mock and production directories (the package must also be the same). This way, when you're switching build variants, the compiler will refer to either the Module class in mock or production flavor, allowing you to inject different implementations depending on the flavor.
Check out this reference on source sets: http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Sourcesets-and-Dependencies
This answer might also be helpful: How the flavor-specific variants are working?
I'm trying to test a method in a jar library, and was hoping to use Robolectric to do my unit testing, rather than running the tests in the Android emulator. I'm running into a problem though, where Robolectric needs an androidmanifest.xml file that doesn't exist, since I'm building a library...
Is there any way to run Robolectric tests without an app?
Here's what my test case and code under test look like:
public class ObjectUnderTest {
methodUnderTest(View v) {
...
}
}
#RunWith(RobolectricTestRunner.class)
public class Tests {
#Test
public void methodUnderTest_Test() {
...
}
}
When I run the test suite I get a FileNotFoundException from Robolectric looking for androidmanifest.xml. I've tried using the JUnit4 test runner instead, but then I get the "Stub!" exception when I create a View for the argument to methodUnderTest().
Is there a way to do this besides creating a stub application just for the unit tests? Thanks!
It depends which Robolectric you're using.
If you use 2.0 you could try to annotate your test class with #Config(manifest=Config.NONE).
If you use 1.x I think it's doable but will require more effort:
You should folder create structure similar to Android project and create dummy AndroidManiifest.xml inside
You should extend RobolectricTestRunner and pass through constructor path to this fake Android project