I am trying to test a library developed by me through jUnit, but I'm having some problems. This library requires an activity to be instantiated. However, following the tutorial (http://www.vogella.com/articles/JUnit/article.html), I can not instantiate the object because I dont have the activity. You can create a dummy activity?
Thanks :)
To test an Activity you should normally use ActivityInstrumentationTestCase2. When you invoke getActivity() the Activity under test will be created.
If you are testing a library project, the post android: testing library project would be also of help.
Unit testing Android applications is tricky because of the stubbed out API implementation ("java.lang.RuntimeException: Stub!")
If you want to unit test your Android Activities and such, Robolectric is a nice option: http://pivotal.github.com/robolectric/
Related
I'm a beginner in android tests and what I would like to know is very simple.
I have a button which launch an activity on click and instead of launching the real activity I would like to replace it by the launch of another one.
How can I achieve that?
I'm using Espresso and mockito 2.0+. Thank you.
I doubt that this question still need an answer but in cas, just know that Dependency Injection like dagger will do the job. Inject your real activity on your app and another activity in your test by loading a different module.
I'm trying to use Android Support Test Library (previously android-test-kit) and create tests for one of my projects. It contains some 'functional' code along with UI code in single project.
My intention is to use JUnit4 and not mix with JUnit3, so I use AndroidJUnitRunner.
There's number of test classes created for the 'functional' code which follow JUnit4 and work fine.
Recently I've started to implement tests for UI components. Referring documentation receipt number of tests have been implemented. These activity tests follow JUnit4 style and extend ActivityInstrumentationTestCase2 based on above doc.
The problem that I'm facing now: it's not possible to execute all tests at once. If I try to run package / all tests (Activity and 'functional' are presented in the same project) from IntelliJ Idea - only pure JUnit4 tests get executed. I suspect that the problem is in ActivityInstrumentationTestCase2 which extends TestCase and is not pure JUnit4 test class.
Is it possible somehow to get rid of ActivityInstrumentationTestCase2 in Activity tests using Android Support Test Library (android-test-kit) and have all test running? Or my assumption about the issues rootcause (about TestCase) is wrong?
InstrumentationTestCase, ActivityTestCase and ActivityInstrumentationTestCase2 are deprecated, you should be using ActivityTestRule instead. InstrumentationRegistry is also useful to get a hold of application context and instrumentation instances.
Finally found only possible solution: copy InstrumentationTestCase, ActivityTestCase and ActivityInstrumentationTestCase2 into my project from AOSP source. After that, remove inheritance from InstrumentationTestCase of TestCase. Same way it's done in this project (AndroidJunit4).
There's actually no need for TestCase and these changes and documentation receipt are enough to have activity tests to be JUnit4 and avoid mixing issues.
I have some sourcecode in my android project that just uses plain java code.
I created UnitTests (JUnit) for this classes to test them.
The problem is that the functions use internally some android classes yet.
These are Log and Base64 at the moment.
Now I am looking for a simple way to mock this Classes but I was not able to do so.
I googled and found a lot of mocking tools like jmocking, mockito, robolectric and so on, but I am very confused with this libraries and did not get one of them to work.
I did not find one good step by step tutorial that shows me how to simply mock some android class so I do not get this stub / classnotfound errors.
Questions would be:
What is the most common used android mocking library?
How do I mock some Class that I do not use directly in my UnitTest, but that are used by the functions I call?
Thanks,
Subby
I'm not sure that any mocking library will fully support Android. There are several technical reasons why Android and mocks don't get along.
If you want to unit test a java object that uses the Android API, you usually have to use one of the test case classes in android.test.*. Android classes often need an Android context in order to work correctly.
For a unit test, you usually inject a dependency, but there are limits. After all, you don't unit test the multiplication operation! You can unit test the Android classes, and once you're satisfied they're working, you can assume that they're working correctly.
You'll need robolectric to mock Android classes: http://pivotal.github.com/robolectric/index.html
I'm writing some POJO tests for my Android code.
I want to run them locally with the JDK (not with Dalvik on the emulator) - for speed, JUnit 4, Mockito, and being able to run headless without a device - so I have a separate "Java" project in Eclipse.
If the method I'm testing happens to reference anything from the Android SDK, e.g. android.util.Log, the test fails - this makes sense because android.jar isn't in the classpath. To reproduce I have this test case:
public class FooTests {
#Test
public void testFoo() {
android.util.Log.d("x", "y");
}
}
If I add android.jar explicitly to the test project's classpath, I get exceptions like
java.lang.RuntimeException: Stub!
at android.util.Log.d(Log.java:7)
at com.example.FooTests.testFoo(FooTests.java:39)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Is there a way to make the code work without mocking out every last bit of Android SDK dependency? Perhaps a mocked-out android.jar already exists?
EDIT: For now I ended up wrapping classes like android.util.Log and injecting them into the instances, for classic IOC-based testing. Scott's PowerMock suggestion is my next step when I'll need it.
LATER EDIT: Robolectric!
I had the same problem. I wanted to test simple POJOs locally.
Specifically, my code wanted to use android.util.Base64.
What I ended up doing was to use the SDK to install the Android 4 sources, and copied the android.util.Base64 class to my project.
Surprisingly enough, this worked.
There's no mocked out android.jar that I know of. I use Powermock to mock everything out. One thing you can do to help with the heavy mocking is to make your extended android classes like activity, fragments, broadcasters, etc. thin and have them delegate to pojo classes. You could make a risk based decision not to isolation unit test the android extended classes, and instead integration unit test them via the android testing framework or something else like Robotium.
For true isolation unit testing in Android, for me unit testing on the java jvm mocking all out all collaborating classes is the best way to go.
I had the same problem. I wanted to test simple business logic locally.
Specifically, my code uses android.util.SparseArray<E>.
I tried 3 different approaches to make it testable with junit outside android.
In my business logic I created an interface and attached it to MySparseArray<E> that inherits from SparseArray<E>. In the junit-test I re-implemented the interface using HashMap<Integer, E>. This works but in the long run this is to much work to make business logic unit-testable if other android.* are required.
As suggested by #Tal Weiss I added the android java sources of the required classes: android.util.SparseArray.java that uses com.android.internal.util.ArrayUtils.java. This works, too but I don't like to add more android sources, especially if there are much more dependencies
I downloaded a stub free binary android.jar for an old android 2.2 from http://grepcode.com/snapshot/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1 and included it as lib into my junit-java-project. This jar contains only classes for namespaces android.*, com.android.*, dalvik.* and framework.base.*. This works too.
Currently I succeeded to avoid using android.* classes except SparseArray<E> in my business layer and has no dependency to Context, Activity or Service. I could have used HashMap<Integer, E> in the android-business layer instead of SparseArray<E>.
unmock-plugin could help https://github.com/bjoernQ/unmock-plugin. In my case it works with SparseArray.
Won't the embedded android/junit tests do what you want?
I have a project with many classes and activities. I would like to test some of those classes by creating another project and using them. Is this possible? I tried creating an Android test project in Eclipse, linking to the project I want to test, creating an activity and there using some of those classes. Unfortunately, I get NoClassDefFoundError. Could you please address me to the right direction on how to create this kind of test?
Thanks!
What you are looking for is JUnit testing. There is plenty out there to get you started.
To test activities you can fire intents using ActivityInstrumentationTestCase2