I am trying to run a Roboelectric Unit test to test if the intended activity is getting started or not, but as I'm getting the following error :
java.lang.NoClassDefFoundError: Could not initialize class
android.os.AsyncTask
I am looking for the solution but no luck so far, Has anyone faced this issue before.
Find below my Test class
#RunWith(RobolectricTestRunner.class)
#Config(constants = BuildConfig.class, manifest = "AndroidManifest.xml", minSdk = 21, maxSdk = 21, application = MyApplication.class)
#PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
public class PushManagerTest {
#Test
public void shouldLaunchNewActivity() throws Exception {
Activity testActivity = Robolectric.setupActivity(TestActivity.class);
Intent expectedIntent = new Intent(testActivity, NewActivity.class);
Intent actualIntent = ShadowApplication.getInstance().getNextStartedActivity();
assertEquals(expectedIntent.getComponent(), actualIntent.getComponent());
}
}
I finally fixed it, dont know if it is the correct way or nor but the tests are working as expected
I had to add the following lines in the onCreate of my Application class
try{
Class.forName("android.os.AsyncTask");
}catch(Throwable ignore) {
// ignored
}
Hope it helps someone
Related
I'm setting up this class for testing my fragment:
#RunWith(RobolectricTestRunner.class)
public class MyFragmentTest {
MyFragment myFragment;
#Before
public void setUp(){
myFragment = (MyFragment)FmyFragment.instantiate(ApplicationProvider.getApplicationContext(), MyFragment.class.getName());
SupportFragmentTestUtil.startVisibleFragment(myFragment);
}
}
But the line
SupportFragmentTestUtil.startVisibleFragment(myFragment);
is throwing the following exception:
java.lang.IllegalStateException: Recursive entry to executePendingTransactions
Did I miss something in my setup? I've tried many things and this is the closest I've been to starting my fragment with roboelectric.
If you need more info, feel free to ask.
The problem was with a Glide Bug when using roboelectric.
I have been experiencing something really weird. Maybe someone can explain me where I am making mistake.
I have a following scenario in a feature file
#DeleteUserAfterTest
Scenario: Testing a functionality
Given admin exists
When a user is created
Then the user is verified
My #After method in Hooks class looks like following
#After
public void tearDown(Scenario scenario) {
if (scenario.isFailed()) {
final byte[] screenshot = ((TakesScreenshot) driver)
.getScreenshotAs(OutputType.BYTES);
scenario.embed(screenshot, "image/png"); //stick it in the report
}
driver.quit();
}
I am using the following method in my step definition to delete the created user based on tag passed in the Test Scenario as follows:
#After("#DeleteUserAfterTest")
public void deleteUser(){
//Do fucntionalities to delete user
}
My test runner looks something like this:
import io.cucumber.testng.AbstractTestNGCucumberTests;
import io.cucumber.testng.CucumberOptions;
#CucumberOptions(
plugin = {"pretty","com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter:", "json:target/cucumber-report/TestResult.json"},
monochrome = false,
features = "src/test/resources/features/IntegrationScenarios.feature",
tags="#DeleteUserAfterTest",
glue="Steps")
public class IntegrationTest extends AbstractTestNGCucumberTests {
}
However, when I launch the test case, sometimes my user is deleted in the After("#DeleteUserAfterTest") but sometimes my test does not recognises the tagged After at all. It directly goes to After method in my Hooks class and quits the driver. Maybe someone has encountered this problem or knows a workaround!
Method order is not defined in Java. So you have to tell Cucumber in which order you hooks should be executed. Higher numbers are run first (before hooks are the other way around).
#After(order = 500)
public void tearDown(Scenario scenario) {
}
#After(value = "#DeleteUserAfterTest", order = 1000)
public void deleteUser(){
}
I am pretty new to java, still a lot learn. I have created an interface class called FailedTest. After all of the tests run, I would like to add the failed tests classes to the FailedTest interface class. Once I have all of the failed tests, I would like to create a gradle task to run all of the failed tests again. I am using Junit, Intellij and Gradle.
FailedTest interface class in categories package:------
package myPackage.categories;
public interface FailedTests {
}
TestExecutionListener in listeners:----------
#Category(FailedTests.class)
public void afterTestExecution(TestContext testContext) {
if (testContext.getTestException() != null) {
// i would like to add failed tests to the FailedTest interface class here
FailedTests = testContext.getTestClass();
}
}
In build.gradle I would like create following task:----------
task testFailedTests(type: Test) {ext.getTestMethodsFromStorage = { ->
//return a string array of the test classes/methods from the file:FailedTest
}
useJUnit {
include getTestMethodsFromStorage()
}
}
I would appreciate any help or feedback. Thank you!
I have been looking on Google for this error, and most of the answers I have found is to move junit dependence, to the top. Or use another mocking framework. I already moved the dependence and still fails, and the whole project uses mockito and powermock.
This is in resume, the code.
package co.pack.session;
import com.google.gson.JsonObject;
import org.junit.Test;
import co.pack.Session.Organization;
import static org.junit.Assert.assertEquals;
public class TestOrganization {
#Test
public void testLoadJson() {
JsonObject json = new JsonObject();
json.addProperty("theme_color", "red");
Organization organization = new Organization();
organization.loadFromJson(json);
assertEquals("red", Organization.getThemeColor());
}
}
Implementation
public static void loadFromJson(JsonObject json) {
Organization.name = json.has("name") ? json.get("name").getAsString() : "";
Organization.image = json.has("image") ? json.get("image").getAsString() : "";
printActualOrganization();
}
private static void printActualOrganization() {
Log.i(TAG, "_name_ " + name);
Log.i(TAG, "_image_ " + image);
}
It fails on a Log line
Log.i(TAG, "_name_ " + name);
And got this
java.lang.RuntimeException: Stub!
at android.util.Log.i(Log.java:9)
at co.mobico.Session.Organization.loadJson(Organization.java:50)
at co.mobico.session.TestOrganization.testLoadJson(TestOrganization.java:28)
Log lines, never causes any error on my test, I don't know what is happening in this case.
You can try add the following options to your app build.gradle.
android {
testOptions {
unitTests.returnDefaultValues = true
}
}
This should prevent you from getting this RuntimeException, because in this case the Android-Methods will return default values. Be aware that this might raise other problems, e.g. when using TextUtils.equals(...).
Basically I agree with the strategy to mock every dependency of your unit under test, but you can use the return values as a kind of workaround.
The problem is that you call a method directly on a mock.
You usually don't do that.
Usually you create a normal instance of your class under test (cut) and mocks for the dependencies it communicates with:
#Test public void exampleWithMocks(){
// arrange
DataTransferObject dto = new DataTransferObject();
dto.setSomeProperty(SOME_PRIMITIVE_VALUE_OR_STRING);
SomeServiceTheCutDependsOn dependency = mock( SomeServiceTheCutDependsOn.class);
ClassUnderTest cut = new ClassUnderTest(dependency);
// act
Object result = cut.doSomethingWith(dto);
// assert
assertThat(result,notNullValue());
verify(dependency).expectedMethodCall(dto);
}
I'm investigating the reason why the following scenario causes NoClassDefFoundError, which involves the use of jmockit and JNI.
Here's the classes:
MyJNI.class
class MyJNI {
MyJNI() {}
public static final native int getInt();
}
MyTestInterface.class
public interface MyTestInterface {
int INT_FROM_JNI = MyJNI.getInt();
}
MyTestImp.class
public class MyTestImp implements MyTestInterface {
public MyTestImp() {}
}
DummyTest.java
#RunWith(JMockit.class)
public class DummyTest {
#Mocked
MyTestInterface myTest;
#Test
public void dummy() { assertTrue(true); }
}
FailingTest.java
#RunWith(JMockit.class)
public class FailingTest {
#Mocked
MyTestImp myTest;
#Test
public void shouldPass() { assertTrue(true); }
}
If we run DummyTest.java and FailingTest.java in sequence (the order matters), the test in FailingTest.java fails with the error message "java.lang.NoClassDefFoundError: xxx.xxx.xxx.MyTestInterface".
Specifically, any of the following change corrects the error:
(a) running the tests in reverse order: FailingTest.java and then DummyTest.java
(b) in "DummyTest.java", change "MyTestInterface myTest;" to "MyTestImp myTest;"
(c) in "MyTestInterface.class", change "int INT_FROM_JNI = MyJNI.getInt();" to "int INT_FROM_JNI = 1;".
(d) in "FailingTest.java", change "MyTestImp myTest;" to "MyTestInterface myTest;"
I couldn't find a good explanation to this. In this case the unit tests are not independent anymore. It looks like in the scenario mock MyTestInterface would cause problem in the other test files when trying to use MyJNI, and in this case would make MyTestInterface not found in runtime.
Anyone has any clues of how to explain this? Thanks!