Mockito vs Test Implementation of class - android

I have been going through source code of Volley and have found that for every class or interface there is a test implementation.
Is it preferable to write Test class for every other class than using Mockito to just mock objects?

A broad question but let's collect the underlying facts:
writing your own custom test "stubs" enables you to implement your "own" vision of "test support"
especially, you do not have any dependencies to a mocking framework
In other words: you decide to re-invent the wheel to a certain degree. That prevents you running into bugs other people put down, at the risk of making your own mistakes.
In that sense, this boils down to the old discussion "buy or make yourself".
When talking about test cases, there are various experts that suggest to not rely on mocking frameworks. So this is a common practice, but I think a "minority" one.
My personal two cents here: ideally, you should write production code that can be tested without any mocking framework. But that isn't always possible. And for those cases, you have one mocking framework in your toolbox. You know how to use that in a reasonable way to get your testing done. I would find it way too cumbersome to do all test stubs manually. A lot of effort for a relatively small gain.

Related

Mock FingerprintManager in Android tests

Is there a way to simulate or mock FingerprintManager.authenticate()? I want to write instrumented tests for my fingerprint authenticator.
I'm fine if there's a solution with a restriction that the tests can be run either on an emulator or a device. I use JUnit 4.12.
I might suggest that you don't mock it, in the spirit of not mocking things you don't own. What I might suggest instead (from the above link):
The prescription implied by "don't mock what you don't own" is to introduce your own shim/wrapper/adapter around it. This effectively cordons off the dependency to a single place in your codebase and contextualizes it in the consistent and easy-to-use style you're trying to promote within your codebase. If there's anything awkward about how one needs to invoke the dependency (maybe a chaining API, multi-step invocation, repetitive default configuration, etc.), it can be swept under the rug into that common adapter.
This feels like an instance where the humble object pattern might be appropriate.

Trying to fit a "clean architecture" on an iOS app

Recently I’ve been rethinking my android architecture project, trying to adapt it to a more “clean architecture”, specifically, the kind of design suggested by “Uncle Bob”.
Which it involves several layers of abstractions, a nice isolation of responsibilities and a very strong dependency inversion achieved by dependency injection; which, ultimately, leads to a very decoupled-portable system. A perfect candidate to be tested by unit testing and integration testing.
In my android implementation I’ve ended up having three different modules or layers:
-domain: entities, interactors, presenters (pure java module)
-data: (acts as a repository to supply the data to the domain) (android library module)
-presentation: ui related stuff, fragments, activities, views, etc (android application module)
So, I’m trying to figure out what would be the best approach on the iOS ecosystem.
I’ve tried creating a project with multiple targets to achieve the same solution:
-domain: command line target (which seems very weird but I think is the most pure swift target available)
-data: cocoa touch framework
-presentation: cocoa touch framework
With this approach I can use these targets in the way I did with android modules. But the first caveat I’ve found it is that I need to add manually every new file to the dependent target.
But my knowledge is very limited in projects with multiple targets. I mean I’ve never created an iOS application with multiple targets. So I don’t know even if the solution would be use a framework (cocoa touch/cocoa) as a target instead of a command line module for the domain layer.
Any thought would be really appreciate.
Thanks!
Uncle Bob's Clean Architecture absolutely applies to iOS, Swift, and Obj-C. Architecture is language agnostic. Uncle Bob himself codes mostly in Java but in his talks he rarely mentions Java. All his slides do not even show any code. It is an architecture meant to be applied to any project.
Why am I so sure? Because I've studied MVC, MVVM, ReactiveCocoa, and Clean Architecture for 2 years. I like Clean Architecture the best, by far. I tested it by converting 7 Apple sample projects to using the Clean Architecture. I've used this approach exclusively for over a year. It works out better every time.
Some of the benefits are:
Find and fix bugs faster and easier.
Extract business logic from view controllers into interactors.
Extract presentation logic from view controllers into presenters.
Change existing behaviors with confidence with fast and maintainable unit tests.
Write shorter methods with single responsibility.
Decouple class dependencies with clear established boundaries.
We also added a router component so we can use multiple storyboards. No more conflicts.
Writing unit tests is greatly simplified too because I only need to test the methods at the boundaries. I don't need to test private methods. On top of that, I didn't even need any mocking framework because writing your own mocks and stubs becomes trivial.
I've written my experience for my last 2 years studying iOS architecture at Clean Swift I also put together some Xcode templates to generate all the Clean Architecture components to save a ton of time.
UPDATE - To answer #Víctor Albertos's question about dependency injection in the comment below.
This is a really great question and demands a long detailed answer.
Always keep the VIP cycle in mind. In this case, the doSomethingOnLoad() method is not a boundary method. Rather, it is an internal method invoked only within CreateOrderViewController. In unit testing, we test a unit's expected behavior. We give inputs, observe outputs, then compare the outputs with our expectations.
Yes, I could have made doSomethingOnLoad() a private method. But I chose not to. One of the goals of Swift is to make it easy for developers to write code. All the boundary methods are already listed in the input and output protocols. There is really no need to litter the class with extraneous private modifiers.
Now, we do need to test this behavior of "The CreateOrderViewController should do something on load with this request data" somehow, right? How do we test this if we can't invoke doSomethingOnLoad() because it is a private method? You call viewDidLoad(). The viewDidLoad() method is a boundary method. Which boundary? The boundary between the user and view controller! The user did something to the device to make it load another screen. So how do we invoke viewDidLoad() then? You do it like this:
let bundle = NSBundle(forClass: self.dynamicType)
let storyboard = UIStoryboard(name: "Main", bundle: bundle)
let createOrderViewController = storyboard.instantiateViewControllerWithIdentifier("CreateOrderViewController") as! CreateOrderViewController
let view = createOrderViewController.view
Simply calling the createOrderViewController.view property will cause viewDidLoad() to be invoked. I learned this trick a long time ago from someone. But Natasha The Robot also recently mentioned it too.
When we decide what to test, it is very important to only test the boundary methods. If we test every method of a class, the tests become extremely fragile. Every change we make to the code will break many, many tests. A lot of people give up because of this.
Or, think about it this way. When you ask how to mock CreateOrderRequest, first ask if doSomethingOnLoad() is a boundary method that you should write test for. If not, what is? The boundary method is actually viewDidLoad() in this case. The input is "when this view loads." The output is "call this method with this request object."
This is another benefit of using Clean Swift. All your boundary methods are listed at the top of the file under explicitly named protocols CreateOrderViewControllerInput and CreateOrderViewControllerOutput. You don't need to look elsewhere!
Think about what happens if you were to test doSomethingOnLoad(). You mock the request object, then assert that it equals to your expected request object. You are mocking something and comparing it. It's like assert(1, 1) instead of var a=1; assert(a, 1). What's the point? Too many tests. Too fragile.
Now, there is a time when you do mock CreateOrderRequest. After you've verified the correct CreateOrderRequest can be generated by the view controller component. When you test CreateOrderInteractor's doSomething() boundary method, you then mock CreateOrderRequest using interface dependency injection.
In short, unit testing is not about testing every unit of a class. It is about testing the class as a unit.
It is a mindset shift.
Hope that helps!
I have 3 series of draft posts in Wordpress on different topics:
In-depth look at each of the Clean Swift components
How to break up complex business logic into workers and service objects.
Writing tests in Clean Swift iOS architecture
Which one of these do you want to hear more first? Should I bump up the series on testing?
In my opinion Clean Architecture is a set of ideas, rules, principles... to make a code better.
[Android Clean Architecture]
With this approach I can use these targets in the way I did with android modules.
You are able create a target[About](application target or framework target...) but it depends on your needs
If you read Architecting Android...Reloaded from Fernando Cejas
you might have seen that I used android modules for representing each layer involved in the architecture.
A recurring question in discussions was: Why? The answer is simple… Wrong technical decision
The idea is that is not necessary to use some build components to implement Clean Architecture

what to unit test, in android apps

My apps are mostly GUIs that communicate to a server for most of their information. If anything goes wrong it will usually be in the network call or making a wrong assumption about a JSON object.
Unit Tests are not good for these network-related and i/o related tasks, otherwise, they won't be called unit tests.
SO I am trying to gather the point of Unit Tests in my case. Why would I test if an Android button can click or an EditText can see what I type? I just don't understand the utility of implementing these tedious tests
private void initElements(){
placeButton = (Button) findViewById(R.id.currplace);
placeButton.setText(MainActivity.this.getString(R.string.findingLocation));
placeButton.setEnabled(false);
selectplaceLayout = (LinearLayout)findViewById(R.id.selectplaceLayout);
selectplaceLayout.setVisibility(View.GONE);
splash = (RelativeLayout)findViewById(R.id.splashbg);
infoLayout = (LinearLayout)findViewById(R.id.infoLayout);
}
if this above method passed, which all my activities run in onCreate, then I know the app works. A unit test of this would be a redundant time-consuming thing to create. Time-consuming because I am not familiar with all the methods in the jUnit and Android testing framework.
So, long story short, what's the point? Is there a particular way I should be thinking about these tests? All examples and tutorials I've seen so far only talk about the simplest examples, for the sake of brevity, but I cannot think of any practical uses for unit tests in a predominately client-server app.
What am I expected to discover by accessing the android views that I already know I declared and initialized? I must be thinking about this in a too limited way
so, insight appreciated
There are lots of facets in your question, but to my opinion - you probably don't need unit-tests in your project.
Unit tests really shine when you need lots of business logic to your project. In this case you probably want to divide your application into multiple layers (say, 3-tier architecture) to, among other, add some natural isolation for business-logic layer and cover it with safety net of unit tests.
This safety net covers your ass during refactor of the business layer, and that's one of the main things you what from unit tests (TDD can offer some nice extra side effects though).
However, it's not all unicorns and rainbows and unit-test may cost, and sometimes they cost a lot. Good unit tests are isolated (i.e. deal with small chunks of code). This means that you have to add layers of abstraction in order to put your classes under the test.
This may have positive affect on your system or negative one. Layering makes your system more flexible with cost of increased complexity.
Having that said - the value of the unit-tests is proportional to the amount of abstract business-logic you are going to introduce in your project. You may think of it also this way - if it is overkill to add abstract layers to your architecture - don't add unit-tests - they will only make things more complicated (architecture and build wise).
Based on your description - your typical app tend to be pretty much presentation layer for some external server-side. It does not that much except presenting information on android handset and transforms user actions to commands to server-side where main business logic gets done (controlling).
With this approach most of the code you probably write is related to "how to display this and that" or "how to signal server in this and that case". This sort of code is obviously heavily depend on platform and this mean that if you do want to put it under test you'll have to mock lots and lots of Android specific code\behavior.
Now, Android is somewhat specific platform. It was designed to be both performance optimized and allow developers to start and produce apps quickly. Often this means some amount of "swiss-knife" classes you have use\extend and generally this speeds up writing code, but mocking those classes can become a real hell. Not to mention that you have to have understanding of how platform works under the hood to make those mock useful. In other words overhead from making those test is going to be high.
Another thing that is wrong with testing presentation layers is that they tend to change much more dynamically than business layers. And, of course this mean that you'll have to refactor thee tests which adds even more overhead.
I have to say one thing about various utility/helper classes though. Even if these classes are belong to presentation layer and do depend Android code, but do some rather non-trivial logic and it is easy to mock and write unit tests for them, it might actually be a good idea to do this. However, if you do have lots of such code - this is might be a signal that you haven't designed your architecture/layering well, and need to rethink what you are doing.
In the end to answer your question you have to answer these questions first:
Will it be overdesign to add abstract layer that is separated from the platform to your application (seems like in your case it will)? If yes - do not use unit-tests - they will only slow you down. If no - do use them.
Are you going to refactor a lot? If that's large project with lots of code and thus maintenance - you probably will, so invest in layering and unit-tests (but, at a glance, it does not seem that this is your case). If that is not your case - do not bother with unit-tests and go fast.
Do you need to mock platform a lot to write your unit tests? If yes (seems to be your case) - don't write unit tests - they do not worth the effort.
Hope this will help.
UTesting in Android generally takes relevance when you are using some layering with a good architecture. Nowadays the most popular is Clean Arch, which is all about maintainability and testability. Every part of the architecture has exactly one purpose. We just need to specify it and check that it actually does its job every time.
When testing use cases we should test that use case calls correct methods in repositories or executes other use cases. We should also test that use case returns proper callback.
When testing repositories, you should arrange DAOs – make them return or receive some dummy data, and check that repository is handling the data in a proper way.
When testing mappers (converters), specify input to the mapper, and exact output you expect from the mapper, then assert they are equal. Do the same for services, parsers etc.
Leaving the architecture besides any good modular and decoupled design will contain business logic in functions and classes, and if those follow single responsibility principle (they should), then likely should be tested.
Think about testing before and during coding. That way you can write testable and decoupled code. Use your tests as class specification, and if possible write them before the code.
Examples and expanded info: https://five.agency/android-architecture-part-5-test-clean-architecture/
from Android.Docs
For testing Android apps, you typically create these types of automated unit tests:
Local tests: Unit tests that run on your local machine only. These tests are compiled to run locally on the Java Virtual Machine (JVM) to minimize execution time. Use this approach to run unit tests that have no dependencies on the Android framework or have dependencies that can be filled by using mock objects.
Instrumented tests: Unit tests that run on an Android device or emulator. These tests have access to instrumentation information, such as the Context for the app under test. Use this approach to run unit tests that have Android dependencies which cannot be easily filled by using mock objects.
Note: Unit tests are not suitable for testing complex UI interaction events. Instead, you should use the UI testing frameworks, as described in Automating UI Tests.

Robotium with Mockito or Easy Mock

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.

Does it make sense to use Guice for Android

I'm debating using guice in an android project that is quite complex and has a lot of business logic. Guice seems like a good fit, but whenever I start reading deeper into it, it starts to look more complicated than it needs to be.
One thing I don't understand is: if Guice is so great and the best way to write java code, how come there is so little Android code that uses Guice... and why didn't Google use guice internally for Android?
Guice totally makes sense to be used and in fact is used in a whole bunch of applications. The extension RoboGuice adds some niceties for Android that makes it super productive to use.
In fact I can not imagine writing an Android app without it. Too painful.
Check out the links to apps using Roboguice on the website (e.g. Google Docs, OpenTable...). Also other apps like the Square app are known to use Guice directly.
It totally makes sense .. go do it!
Together with Robolectric it will also make your testing efforts easier.
PS: I am a committer on RoboGuice so I am partial ;-)
PPS - June 2013: Recent developments have given rise to other annotation/dependency injection based frameworks that do most of the work at build time and therefore avoid the performance hit of the runtime reflection (that is slow on Android) and are therefore more suitable for performance critical work - check out Dagger and AndroidAnnotations if you are interested in that.
Actually google discourages using Guice or RoboGuice in android applications due to memory overhead.
Source:
http://developer.android.com/training/articles/memory.html#DependencyInjection
5.11.2014 Edit:
There is a dedicated fast dependency injection library for android. I can see more and more people using it:
http://square.github.io/dagger/
13.04.2015 Edit:
Google released its own version of dagger, which does not use reflection in runtime:
http://google.github.io/dagger/
You know there is RoboGuice? It's Guice for Android.
The problem with demonstrating the strengths of a dependency injection framework is that it isn't possible to achieve it with a simple Hello World application. These frameworks show their value only in big systems with a lot of complexity. Also, they have a somehow steep learning curve.
Therefore it is quite normal that you can't find enough tutorials - open source projects that use Guice. This will be most often used in enterprise applications that do not get published.
As why Google doesn't use Guice, Guice doesn't fit everywhere. It adds a perfomance overhead and it doesn't make sense to use it in places, where it isn't needed.

Categories

Resources