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
Related
I am trying to find a mocking framework that works with Xamarin Android. So far I have tried Rhino Mocks and Moq but both depend on System.Web.dll which does not seem to be supported by Xamarin. I have included the System.Web.Services reference to my project with no luck.
So my question is what mocking frameworks out there are compatible with Xamarin projects? This is just for simple mocking not even specific android classes like activities, although one that could combine both would be best.
From what I've observed, there really is no mocking frameworks that work well with Xamarin. On the iOS side, this is mainly due to the inability to use Reflection.Emit because of the code generation restriction imposed by Apple. I realize you're on Android, so that restriction does not apply to you. However, other restrictions arise, like you've found with RhinoMocks. My favorite mocking framework is Moq, but I can't use it with Xamarin because of some of the configuration namespaces that are implemented in .NET, but not in Mono.
So, your best bet is just manual mocks. I know that's not the answer you want to hear, but it seems to be the consensus.
You can use True Fakes (http://truefakes.net) mocking framework to solve your issues. It doesn’t use Reflection.Emit at runtime, but it automatically generates mocks at compile time and add it to assembly where unit-tests are. This allows you to use True Fakes for writing unit tests with fully isolated system under test for Xamarin.Android and Xamarin.iOS and running them directly on the device!
You can add it to your project via NuGet (https://www.nuget.org/packages/TrueFakes/).
Please see more information about True Fakes at http://truefakes.net.
PS. I’m developer of True Fakes mocking framework.
I've been using a mock generator called PCLMock.
I had to fork it to get it working with .netstandard, you can give it a go by cloning it and building it from here:
https://github.com/pellet/PCLMock
It works by generating code before compile time, therefore not needing the reflection apis missing in AOT compiled xamarin projects.
Otherwise you could always go functional style and pass in your dependencies as delegates/Funcs, this way you don't need to generate mocks for interfaces, you can use a builder class for injecting mocked out lambdas in unit tests.
Can we use JUnit for test driven development in Android ? If not, is there an alternative similar to JUnit ?
I searched a bit on google and also read a SO post Android Test Driven Development
It looks like Android was never made with TDD in mind. I wanted to be sure before I begin learning TDD and doing Android development at the same time.
I think you can completely rely on Robolectric for running your tests in JVM. You get to use JUnit4 for testing your POJOs and Robolectric provides you the support for testing the Android components.
I am also a beginner in TDD for Android Development. I find Robolectric really useful for test driving my code.
This video will tell you almost everything it provides you for unit testing the Android code.
UPDATE:
With the Android studio support and the new Android ecosystem, now unit testing can be done as a first class practice. Refer http://developer.android.com/training/testing/unit-testing/local-unit-tests.html for more details.
There are couple of good approaches to test drive the android code. The most effective ones I have found so far is using MVVM(model-view-viewmodel) or MVP(model-view-presenter) approach, where the business logic as well as presentation logic is decoupled from the view and can be easily be unit tested.
Yeah we can use JUnit for test driven development. To initiate with you can refer to following
link : http://developer.android.com/tools/testing/testing_android.html#JUnit
Following the documentation we can use the junit.framework to have unit testing done.
Here is a bit of explanation of the problem space: http://www.techwell.com/2013/04/applying-test-driven-development-android-development
The conclusion is you should use Robolectric. Unfortunately Robolectric is slow, and if you follow TDD even on a pragmatic level, you will end up with a couple of hundreds of test, that will run for couple of 10 seconds. And that is not you want to do with TDD. TDD test package should run at most in seconds.
My advise is:
Create wrapper classes around Android classes that simply call the Android class.
Write your app logic in pure Java.
Use Junit (or TestNG or whatever pleases you) to test you model/business logic
Use occasionally Robolectric for the wrapper classes (probably you won't have to use)
(You can write integration tests that use multiple classes, Robolectric, etc. but only run it on a separate Continous Integration server eg. hourly)
With this approach your logic will be more portable as well.
I'm new to Android testing and I`d really appreciate if some of you could help me with that.
I'm using robotium as automation testing framework (so far so good), but I have no idea how I use mockito or Easy Mock to add some mocks to my tests. I'm really stuck with that. Can someone give me some simple example on how to achieve this?
Thanks in advance
Short Answer/opinion
I don't recommend using Mockito for Android unit testing. The Android environment feels too complex to mock. The basic approach for Android unit tests is to run them within the emulator. Thus many of the container classes are already present and need not be mocked.
Long Answer
I also am relatively new to the world of Android unit testing. I have long written server-side unit tests and found Mockito to be one of the best tools around to simplify unit testing. Mockito is very helpful in mocking the behavior of complex objects. This helps to break any dependencies that your code-under-test may have on containers (e.g. servlet container or OSGI container), or on other complex collaborators (e.g. database connection classes).
This sort of mocking works well when your containers/collaborators have well-defined interfaces.
A couple months back, I decided to try Mockito with Android development. I found that Mockito does work if you have at least 1.9.5 and dexmaker. Dexmaker handles runtime byte-code generation for Android's Dalvik VM.
The first thing I tried in my very first test was to mock android.content.Context, and I found that is was HARD. First I tried to mock only the methods that I called directly, but then I found that these called into other methods which had dependencies on application resources, ... Eventually the mocking got so complicated that it defeated the purpose of using Mockito in the first place.
So I gave in and started using the Android unit test helper classes (AndroidTestCase, ActivityUnitTestCase, ...). I was discouraged that I now had to rely on the emulator which meant SLOW test execution. Perhaps Mockito still has a place in this type of test. It might be useful for mocking things like external data sources.
Anyways, this is just my 2 cents.
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?
As the title says, I want to know, if possible, how can I create a stub from Bundle to run at JVM (so not Dalvik). Since its part of android.os package, may be that is related to that impossibility.
My point is due to the fact that I want to use a mocking framework, which run at JVM, to test the Activity.onCreate() method.
I've already found this link but it seems they use a stripped custom android.jar since its rather experimental and unproven (yet I could not reproduce even with their jar, maybe I need some sleep).
If there is another alternative to mock testing this, any insights will as always be appreciated.
Thanks.
I've been successfully writing unit tests on the java jvm for classes that interact with android.jar classes. I use Powermock to mock out all android classes (like Bundle).
This link talks about using a version of the android jar that does not throw the "stub" exception on the java jvm. I have not needed to use a different version of the android jar. Using Powermock I've been able to successfully mock out anything I need to. For me this unit testing technique is not experimental.
Having said that - the unit tests for classes that extend activities, fragments, etc. become very much mock heavy. I feel it's good to move as much logic as you can into pojo classes, keeping your android extended classes as thin as possible. You can decide then if you feel it's worth isolation junit testing the android extended classes. It can certainly be done if you wish. You can also consider an integration testing framework like the one provided by Android or Robotium to test your android extended classes and their lifecycles.