How mock Companion object in Android using Mockito - android

I been trying to run a unite test and I am now facing some issue in mocking the Application Context. I tried mockStatic() but is not working. I am using Junit 5 and org.mockito:mockito-inline:3.4.6 for testing.
class ApplicationContext : Application() {
init {
instance = this
}
companion object {
private var instance : ApplicationContext? = null
fun applicationContext() : Context = instance!!.applicationContext
}
When I run my test this throws a NullPointerException.
java.lang.NullPointerException
at com.adaptavant.yoco.Util.ApplicationContext$Companion.applicationContext(ApplicationContext.kt:14)
at com.adaptavant.yoco.viewModel.LoginViewModelTest.setUp(LoginViewModelTest.kt:48)
Can Someone help me out here.

There is no ApplicationContext available in unit test - you need to use instrumentation tests for that:
Local unit tests:
Use these tests to minimize execution time when your tests have no Android framework dependencies or when you can mock the Android framework dependencies.
Instrumented tests
These tests have access to Instrumentation APIs, give you access to information such as the Context of the app you are testing, and let you control the app under test from your test code.
Source

Related

JUnit tests always pass when executing in device

This simple test
#RunWith(JUnit4::class)
class Test {
#Test
fun test() {
assert(false)
}
}
Unexpectedly, this passes when put in androidTest (both through Android Studio and in the terminal), but obviously fails as expected when put in test.
You need to use JUnit assertions for running tests. The base assert() functionality is normally disabled when running "production" code, so you cannot depend that a plain assert statement will throw an assertion exception.
Use:
org.junit.Asserts.assertTrue( false )
to make the test fail properly.

Failing to run Instrumented tests on a new Android Kotlin project

I just created a new android application with Kotlin Support.
When I've tried to run the default instrumented tests it does not run and shows me this message:
Class not found: "oussaki.com.pos.ExampleInstrumentedTest"Empty test suite.
This the Instrumented test class that I'm trying to run:
#RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
#Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getTargetContext()
assertEquals("oussaki.com.pos", appContext.packageName)
}
}
This is a known issue: https://issuetracker.google.com/issues/38452937 which hopefully will be fixed in the next release.
For the time being you can manually go to 'Edit Configurations' and add the configuration for the specific class/method you want to run under 'Android Instrumented Tests'.
You could also try the latest canary build: https://developer.android.com/studio/preview/index.html but personally I've had trouble getting it to work with my project.

Android Test Orchestrator and custom Application class

I gave a try to Android Test Orchestrator and it doesn't see any tests if Application class were changed. Pretty easy to reproduce.
In Android Studio 3 preview Beta 6 create simple project with wizard
Create custom runner like:
class CustomTestRunner : AndroidJUnitRunner() {
override fun newApplication(cl: ClassLoader?, className: String?, context: Context?): Application {
return super.newApplication(cl, TestApplicationClass::class.simpleName, context)
}
}
Replace instrumentation runner with new one
No test found after running instrumented tests
Any ideas? Looks like the Orchestrator depends on application class name from manifest.
I use this configuration to use special Dagger dependencies for tests.
I had the similar issue, with a custom test runner. Make sure that your TestApplicationClass does not crash at runtime. If the custom runner crashes then orchestrator will not be able to get information about the tests and will return the message:
No tests found. This usually means that your test classes are not in the form that your test runner expects (e.g. don't inherit from TestCase or lack #Test annotations).
That is what happened to me in my custom runner.
Good luck!

How to unit test POJO which uses Android SDK classes on JVM?

I have a Java class called Warehouse which is using Android's Bundle. When trying to unit test it, I get the following exception:
java.lang.RuntimeException: Stub!
The class looks like that:
public class Warehouse {
private Bundle items;
public Warehouse(Bundle items) {
this.items = items;
}
}
In the unit test I have the following:
void testInitializeWarehouse() {
Bundle items = new Bundle();
Warehouse wh = new Warehouse(items);
assertNotNull(wh);
}
When I run the test I get java.lang.RuntimeException: Stub!
I know this issue is related to me running the unit test on JVM rather than Dalvik VM, but is there a way to run this unit test on JVM?
Try using Powermock to mock Bundle using its ability to mock a final class as described here - Powermock MockFinal
I found out Robolectric, which is exactly what I was looking for. I could have used mocks but then half of the unit tests will consist of mocks setups etc.
"a unit test framework that de-fangs the Android SDK jar so you can
test-drive the development of your Android app. Tests run inside the
JVM on your workstation in seconds."

Can I use Robolectric to unit test static library jars?

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

Categories

Resources