Android unit test are failing with initializationError if RunWith RobolectricTestRunner - android

My Android unit test is failing with initializationError if RunWith RobolectricTestRunner.
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.robolectric.RobolectricTestRunner;
import static junit.framework.Assert.assertEquals;
#RunWith(RobolectricTestRunner.class) // If I use #RunWith(Junit4.class) it works
#Config(application = Application.class)
public class LoginActivityTest {
#Test
public void sampleTest() {
assertEquals("actualMessage", "expectedErrorMessage");
}
}
Here is the entire stacktrace:
java.lang.TypeNotPresentException: Type [unknown] not present
at java.base/java.lang.reflect.Method.getDefaultValue(Method.java:682)
at java.base/sun.reflect.annotation.AnnotationType.<init>(AnnotationType.java:132)
at java.base/sun.reflect.annotation.AnnotationType.getInstance(AnnotationType.java:85)
at java.base/sun.reflect.annotation.AnnotationParser.parseAnnotation2(AnnotationParser.java:267)
at java.base/sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:121)
at java.base/sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:73)
at java.base/java.lang.Class.createAnnotationData(Class.java:3757)
at java.base/java.lang.Class.annotationData(Class.java:3746)
at java.base/java.lang.Class.getAnnotation(Class.java:3651)
at com.intellij.junit4.JUnit4TestRunnerUtil.buildRequest(JUnit4TestRunnerUtil.java:213)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:47)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: java.lang.NoClassDefFoundError: android/app/Application
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:800)
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:698)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:621)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:579)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:398)
at java.base/sun.reflect.generics.factory.CoreReflectionFactory.makeNamedType(CoreReflectionFactory.java:114)
at java.base/sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:125)
at java.base/sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:49)
at java.base/sun.reflect.annotation.AnnotationParser.parseSig(AnnotationParser.java:440)
at java.base/sun.reflect.annotation.AnnotationParser.parseClassValue(AnnotationParser.java:421)
at java.base/sun.reflect.annotation.AnnotationParser.parseMemberValue(AnnotationParser.java:350)
at java.base/java.lang.reflect.Method.getDefaultValue(Method.java:674)
... 13 more
Caused by: java.lang.ClassNotFoundException: android.app.Application
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
... 31 more
testImplementation in build.gradle for robolectric is 'org.robolectric:robolectric:4.8.1'
jdk version 11
api level 31
gradle version 4.10.1
android studio ChipMunk
Please help! Thank You!

Related

java.lang.RuntimeException: Failed to instantiate test runner class androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner

I keep getting a RuntimeException whenever I execute my test:
package com.example.mytipcalculator
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.action.ViewActions.typeText
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.hamcrest.Matchers.containsString
import org.junit.Rule
import org.junit.runner.RunWith
#RunWith(AndroidJUnit4::class)
class CalculatorTests() {
#get:Rule
val activity = ActivityScenarioRule(MainActivity::class.java)
fun test(){
onView(withId(R.id.cost_of_service_edit_text))
.perform(typeText("50.00"))
.perform(ViewActions.closeSoftKeyboard())
onView(withId(R.id.increase))
.perform(click())
onView(withId(R.id.increase))
.perform(click())
onView(withId(R.id.increase))
.perform(click())
onView(withId(R.id.increase))
.perform(click())
onView(withId(R.id.increase))
.perform(click())
onView(withId(R.id.calculate_button))
.perform(click())
onView(withId(R.id.tip_result))
.check(matches(withText(containsString("$10.00"))))
onView(withId(R.id.totalexpense))
.check(matches(withText(containsString("$60.00"))))
}
}
When I run the previous code, I get the following initialization error:
java.lang.RuntimeException: Failed to instantiate test runner class androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner
Test class class com.example.mytipcalculator.CalculatorTests is malformed. (1 problems):
java.lang.Exception: No runnable methods
at androidx.test.ext.junit.runners.AndroidJUnit4.throwInitializationError(AndroidJUnit4.java:129)
at androidx.test.ext.junit.runners.AndroidJUnit4.loadRunner(AndroidJUnit4.java:121)
at androidx.test.ext.junit.runners.AndroidJUnit4.loadRunner(AndroidJUnit4.java:82)
at androidx.test.ext.junit.runners.AndroidJUnit4.<init>(AndroidJUnit4.java:56)
... 14 trimmed
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at androidx.test.ext.junit.runners.AndroidJUnit4.loadRunner(AndroidJUnit4.java:112)
... 17 more
Caused by: org.junit.runners.model.InitializationError
at org.junit.runners.ParentRunner.validate(ParentRunner.java:418)
at org.junit.runners.ParentRunner.<init>(ParentRunner.java:84)
at org.junit.runners.BlockJUnit4ClassRunner.<init>(BlockJUnit4ClassRunner.java:65)
at androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner.<init>(AndroidJUnit4ClassRunner.java:43)
at androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner.<init>(AndroidJUnit4ClassRunner.java:48)
... 20 more
You have to annotate test() method with #Test annotation:
#Test
fun test() {
...
}

java.lang.NoClassDefFoundError: Failed resolution of: Landroid/telephony/data/ApnSetting$Builder;

I'm trying to create a mobile application to add APN(Access Point Network) into mobile application. Then I used ApnSetting.Builder() according to the android documentation
I implemented it as following in MainActivity class:
package com.example.myapplication;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.telephony.data.ApnSetting;
import android.util.Log;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class MainActivity extends AppCompatActivity {
private static String TAG = "MainActivity";
#RequiresApi(api = Build.VERSION_CODES.P)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create an MMS proxy address with a hostname. A network might not be
// available, so supply a dummy (0.0.0.0) IPv4 address to avoid DNS lookup.
String host = "mms.example.com";
byte[] ipAddress = new byte[4];
InetAddress mmsProxy;
try {
mmsProxy = InetAddress.getByAddress(host, ipAddress);
} catch (UnknownHostException e) {
e.printStackTrace();
return;
}
ApnSetting apn = new ApnSetting.Builder()
.setApnTypeBitmask(ApnSetting.TYPE_DEFAULT | ApnSetting.TYPE_MMS)
.setApnName("apn.example.com")
.setEntryName("Example Carrier APN")
.setMmsc(Uri.parse("http://mms.example.com:8002"))
.setMmsProxyAddress(mmsProxy)
.setMmsProxyPort(8799)
.build();
ComponentName name = new ComponentName(getApplicationContext(), MainActivity.class);
DevicePolicyManager devicePolicyManager = (DevicePolicyManager) getApplicationContext().getSystemService(Context.DEVICE_POLICY_SERVICE);
devicePolicyManager.addOverrideApn(name, apn);
}
}
But it is showing the following error:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.myapplication, PID: 4314
java.lang.NoClassDefFoundError: Failed resolution of: Landroid/telephony/data/ApnSetting$Builder;
at com.example.myapplication.MainActivity.onCreate(MainActivity.java:42)
at android.app.Activity.performCreate(Activity.java:6609)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1134)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3113)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3275)
at android.app.ActivityThread.access$1000(ActivityThread.java:218)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1744)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:7007)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)
Caused by: java.lang.ClassNotFoundException: Didn't find class "android.telephony.data.ApnSetting$Builder" on path: DexPathList[[zip file "/data/app/com.example.myapplication-2/base.apk"],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
at com.example.myapplication.MainActivity.onCreate(MainActivity.java:42) 
at android.app.Activity.performCreate(Activity.java:6609) 
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1134) 
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3113) 
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3275) 
at android.app.ActivityThread.access$1000(ActivityThread.java:218) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1744) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:145) 
at android.app.ActivityThread.main(ActivityThread.java:7007) 
at java.lang.reflect.Method.invoke(Native Method) 
at java.lang.reflect.Method.invoke(Method.java:372) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199) 
Suppressed: java.lang.ClassNotFoundException: android.telephony.data.ApnSetting$Builder
at java.lang.Class.classForName(Native Method)
at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
... 15 more
Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available
So what should I do for that?
The ApnSetting has added in API level 28 means below API level 28 don't have that method ApnSetting.Builder(). That's why it's not working and causing ClassNotFoundException in Android API level < 28.
Option - 1:
If you really want to use this API and don't need to support older
devices just set the minSdkVersion to 28 in your build.gradle or
AndroidManifest.xml
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
...
minSdkVersion 28 // this is important
targetSdkVersion 29
...
}
}
Option - 2:
If your code is deliberately accessing newer APIs, and you have
ensured (e.g. with conditional execution) that this code will only
ever be called on a supported platform, then you can annotate your
class or method with the #TargetApi annotation specifying the local
minimum SDK to apply, such as #TargetApi(28), such that this check
considers 28 rather than your manifest file's minimum SDK as the
required API level.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
...
ApnSetting apn = new ApnSetting.Builder()
...
}

Why does this test trigger a Robolectric Delegate runner RuntimeException?

I'm writing an integration test for a UI component.
The test is outlined as such:
package filter.clear
import android.view.View
import android.widget.SearchView
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.foo. /* ... several business-logic imports */
import org.junit.runner.RunWith
import org.robolectric.annotation.Config
import kotlin.test.assertEquals
#SmallTest
#RunWith(AndroidJUnit4::class)
#Config(manifest=Config.NONE)
class TestClearSearchView {
private fun searchView() = SearchView(ApplicationProvider.getApplicationContext())
fun clearShouldClearSearchViewQuery() {
// Given
val searchView = searchView()
val clearFilterView = ClearFilterView()
// ...
// When
clearFilterView.view.callOnClick()
// Expect
assertEquals(searchView.query, "")
}
}
However, running the test class (or directly the test method) results in Robolectric throwing a RuntimeException:
java.lang.RuntimeException: Delegate runner 'org.robolectric.RobolectricTestRunner' for AndroidJUnit4 could not be loaded.
at androidx.test.ext.junit.runners.AndroidJUnit4.throwInitializationError(AndroidJUnit4.java:92)
at androidx.test.ext.junit.runners.AndroidJUnit4.loadRunner(AndroidJUnit4.java:82)
at androidx.test.ext.junit.runners.AndroidJUnit4.loadRunner(AndroidJUnit4.java:51)
at androidx.test.ext.junit.runners.AndroidJUnit4.<init>(AndroidJUnit4.java:46)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104)
at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.runners.model.RunnerBuilder.runners(RunnerBuilder.java:101)
at org.junit.runners.model.RunnerBuilder.runners(RunnerBuilder.java:87)
at com.intellij.junit4.JUnit46ClassesRequestBuilder.collectWrappedRunners(JUnit46ClassesRequestBuilder.java:86)
at com.intellij.junit4.JUnit46ClassesRequestBuilder.getClassesRequest(JUnit46ClassesRequestBuilder.java:47)
at com.intellij.junit4.JUnit4TestRunnerUtil.buildRequest(JUnit4TestRunnerUtil.java:90)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:46)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at androidx.test.ext.junit.runners.AndroidJUnit4.loadRunner(AndroidJUnit4.java:72)
... 20 more
Caused by: org.junit.runners.model.InitializationError
at org.junit.runners.ParentRunner.validate(ParentRunner.java:418)
at org.junit.runners.ParentRunner.<init>(ParentRunner.java:84)
at org.junit.runners.BlockJUnit4ClassRunner.<init>(BlockJUnit4ClassRunner.java:65)
at org.robolectric.internal.SandboxTestRunner.<init>(SandboxTestRunner.java:56)
at org.robolectric.RobolectricTestRunner.<init>(RobolectricTestRunner.java:92)
... 25 more
You forgot to mark the method as #Test.
## -11,7 +11,6 ##
import com.foo. /* ... several business-logic imports */
+import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.annotation.Config
import kotlin.test.assertEquals
## -34,7 +33,6 ##
+ #Test
fun clearShouldClearSearchViewQuery() {

Why can't Mockito find android.content.Context in android library unit test?

I can't figure out the correct setup that I need to let my unit tests run correctly inside my android library.
My application consists of a 4 modules: 1 application and 3 android libraries.
I want to run a unit test inside one of my libraries and I always get this error:
java.lang.IllegalStateException: Failed to transform class with name ch.leonardbutz.hellosunshine.core.controller.DataHandlerTest. Reason: cannot find android.content.Context
at org.powermock.core.classloader.MockClassLoader.loadMockClass(MockClassLoader.java:296)
at org.powermock.core.classloader.MockClassLoader.loadModifiedClass(MockClassLoader.java:204)
at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass1(DeferSupportingClassLoader.java:89)
at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:79)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:340)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.createDelegatorFromClassloader(JUnit4TestSuiteChunkerImpl.java:161)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.createDelegatorFromClassloader(JUnit4TestSuiteChunkerImpl.java:48)
at org.powermock.tests.utils.impl.AbstractTestSuiteChunkerImpl.createTestDelegators(AbstractTestSuiteChunkerImpl.java:108)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.<init>(JUnit4TestSuiteChunkerImpl.java:71)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.<init>(AbstractCommonPowerMockRunner.java:36)
at org.powermock.modules.junit4.PowerMockRunner.<init>(PowerMockRunner.java:34)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104)
at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:49)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMainV2.main(AppMainV2.java:131)
Caused by: javassist.CannotCompileException: cannot find android.content.Context
at javassist.expr.NewExpr.replace(NewExpr.java:215)
at org.powermock.core.transformers.impl.AbstractMainMockTransformer$PowerMockExpressionEditor.edit(AbstractMainMockTransformer.java:500)
at javassist.expr.ExprEditor.loopBody(ExprEditor.java:212)
at javassist.expr.ExprEditor.doit(ExprEditor.java:91)
at javassist.CtClassType.instrument(CtClassType.java:1465)
at org.powermock.core.transformers.impl.ClassMockTransformer.transformMockClass(ClassMockTransformer.java:65)
at org.powermock.core.transformers.impl.AbstractMainMockTransformer.transform(AbstractMainMockTransformer.java:62)
at org.powermock.core.classloader.MockClassLoader.loadMockClass(MockClassLoader.java:277)
... 31 more
Caused by: javassist.NotFoundException: android.content.Context
at javassist.ClassPool.get(ClassPool.java:452)
at javassist.bytecode.Descriptor.toCtClass(Descriptor.java:592)
at javassist.bytecode.Descriptor.getParameterTypes(Descriptor.java:439)
at javassist.expr.NewExpr.replace(NewExpr.java:188)
... 38 more
I don't quite understand this, because in my opinion I have everything declared correctly in my dependencies...
gradle.build:
apply plugin: 'com.android.library'
android {
compileSdkVersion project.myCompileSdkVersion
defaultConfig {
minSdkVersion project.myMinSdkVersion
targetSdkVersion project.myTargetSdkVersion
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
lintOptions {
abortOnError false
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
testCompile 'org.powermock:powermock-api-mockito:1.7.3'
testCompile 'org.powermock:powermock-module-junit4:1.7.3'
implementation project(':hellosunshine-communication')
compileOnly project(':hellosunshine-model')
}
And my test class:
package ch.leonardbutz.hellosunshine.core.controller;
import android.content.Context;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import ch.leonardbutz.hellosunshine.core.communication.weather.OpenWeatherDataService;
import ch.leonardbutz.hellosunshine.core.data.source.cache.FileWeatherCachingService;
#RunWith(PowerMockRunner.class)
#PrepareForTest({DataHandler.class, FileWeatherCachingService.class, OpenWeatherDataService.class})
public class DataHandlerTest {
private DataHandler dataHandler;
#Mock
private Context contextMock;
#Mock
private FileWeatherCachingService fileWeatherCachingServiceMock;
#Mock
private OpenWeatherDataService openWeatherDataServiceMock;
#BeforeClass
public void setupSuite() throws Exception {
PowerMockito.whenNew(FileWeatherCachingService.class).withNoArguments().thenReturn(fileWeatherCachingServiceMock);
PowerMockito.whenNew(OpenWeatherDataService.class).withNoArguments().thenReturn(openWeatherDataServiceMock);
}
#Before
public void setupTest() {
dataHandler = new DataHandler(contextMock);
}
#Test
public void testLoadWeather_withCachedData() {
// TODO
Assert.assertEquals(true, true);
}
}
Any help would be really appreciated. The whole project can also be found here: https://github.com/ControlTheBit/hello-sunshine

Android Library JUnit Test with Robolectric: java.lang.InstantiationException

When trying to run a JUnit test on an Android Library project with Robolectric i get the following error:
java.lang.RuntimeException: java.lang.InstantiationException
at com.xtremelabs.robolectric.ApplicationResolver.newApplicationInstance(ApplicationResolver.java:56)
at com.xtremelabs.robolectric.ApplicationResolver.resolveApplication(ApplicationResolver.java:36)
at com.xtremelabs.robolectric.RobolectricTestRunner.createApplication(RobolectricTestRunner.java:246)
at com.xtremelabs.robolectric.RobolectricTestRunner.setupApplicationState(RobolectricTestRunner.java:233)
at com.xtremelabs.robolectric.RobolectricTestRunner.internalBeforeTest(RobolectricTestRunner.java:177)
at com.xtremelabs.robolectric.RobolectricTestRunner.methodBlock(RobolectricTestRunner.java:157)
at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.InstantiationException
at sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at java.lang.Class.newInstance0(Unknown Source)
at java.lang.Class.newInstance(Unknown Source)
at com.xtremelabs.robolectric.ApplicationResolver.newApplicationInstance(ApplicationResolver.java:54)
... 20 more
My first idea was that i made a mistake within the test, so i simplified the test run as much as possible:
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import com.xtremelabs.robolectric.RobolectricTestRunner;
#RunWith(RobolectricTestRunner.class)
public class CommonDataTest {
#Test
public void test(){
assertTrue(true);
}
}
but i still get the same error. I set up the Project as described here: http://robolectric.org/eclipse-quick-start/
The strange thing is that it worked with other Android Library Projects without any problems.
Any help would be appreciated! Thank you in advance!
it seemed that Robolectric was unable to create the Application from my library so i replaced the TestRunner:
import org.junit.runners.model.InitializationError;
import android.app.Application;
import com.xtremelabs.robolectric.RobolectricTestRunner;
public class MyTestRunner extends RobolectricTestRunner {
public MyTestRunner(Class<?> testClass)
throws InitializationError {
super(testClass);
}
#Override protected Application createApplication() {
return new Application() {
};
}
}
and used it instead of the RobolectricTestRunner:
#RunWith(MyTestRunner.class)
The tests are running properly now.

Categories

Resources