I have implement unit test with MVP Architecture and every thing went well
with Junit4 and Mokito
But my problem my that when i need to test methods which has database operation
i'm facing two issue
1-getting null pointer Exception when using #RunWith(MockitoJUnitRunner.class)
and mocking the Presenter and View
2-using InstrumentationTestCase and MockContext i'm able to open the data base with no error but when i call verify on database related method the test success but in the coverage i see that this method in the presenter is not covered
Thanks
Without seeing your code I can't really provide a detailed answer, but in general, you could use Robolectric (which uses a real SQLite db) in order to unit-test classes which depend on SQLite database.
Keep in mind, though, that these tests might be slow. In my practice, a unit test that uses SQLite and run by Robolectric test runner can take up to 10 seconds and more.
Related
I am heavily testing my application with unit tests and Espresso tests. My next step is to make sure my application hits all required apis. For that reason I am looking for a way to write a test, which will verify the api calls.
I would really appreciate any suggestions.
What you are describing is called a "unit test". Unit tests are meant to test as many lines of code as possible regardless of UI.
Espresso tests are "instrumentation tests" (or "UI tests") intended to check if the app is responding to UI events correctly. They're not meant to verify the correctness of code, but the correctness of the functionality of the app as used by the user.
You can read about both at the official documentation. You'll find that unit tests are very different than instrumentation tests, and often harder to write because they require more engineering of your code to do correctly. You will likely have to "mock" the various parts of your application to make sure their APIs were called exactly as you expected.
There are 2 main goal when I was writing api tests:
First is component based. The goal was to make sure each class / component makes an api call when certain criteria is met (for example calling an api A when onDestroy() is called)
Second, is to make sure the Apis are called is certain order for the analytics purposes.
The first step I achieved by using unit tests with injected mock objects via Mockito and PowerMockito. PowerMockito was used primarily to mock static methods and to make sure the methods were called at least n times.
For the second step, UI test could be used, since it runs the real application. I have implemented the helper class, which was recording the instances when api requests were made. The script in Espresso was validating the order of api calls by referring the helper class.
I haven't done any testing in Android, so please bear with me if this seems a stupid question.
I'm developing an app which makes a lot of network calls from a restful API service. To make the network calls, I'm using Retrofit2 and RxJava.
What would be the best practice/framework to just test if these calls are working? I've started to read the Google Codelab for testing which uses Junit4 and Mockito, but I don't want to do any clicking in the UI to start a test currently, just checking for different API versions which calls are supported or not.
Here some steps for you that I am using:
Use mockito & junit4, for sure :)
I avoid UI tests for these cases
Pass your retrofit Api as a parameter to a class that you want to test
In the test create a mock retrofit api, pass this one as a parameter so you can choose what you want your "Api" to return e.g. objects or errors (see Mockito.when())
Use RxJava's TestSubscriber to test a method e.g. Observable<Location> getLocationFromApi()
Avoid threading in your testing class (e.g. like .observeOn(mainThread())). If inevitable use awaitTerminalEvents in TestSubscriber. If there is no terminal even rethink your test
General tips:
Try to modularize your code so each class has few functionality -> easier to test.
Be patient and don't expect to write tests for e.g. 5% of your code in just one week :) It's a slow process regardless team size
I have an android app that uses ORMLite/SQLite and I use Robolectric in conjunction with JUnit 4 to allow me to run unit tests in Android Studio and on a Jenkins build server.
Typically I would setup test data in my tests, in the setup, and then run my test scenarios against it but when I tried to do this I started getting issues and exceptions which seemed to be related to files being locked or something and that seems to be a problem others have had... so what I have done up until now is use the create database method in my database helper to create some dummy data which the tests expect to be there.
The problem is my application now needs to plug into a real database and I can't have it setup dummy data when it runs.
If there a way, within my database helper class, to detect if the code is executing on a device or within Robolectric?
This is what works well for me on Robolectric 3.
public static boolean isRoboUnitTest() {
return "robolectric".equals(Build.FINGERPRINT);
}
To start with, I'll say that you shouldn't be putting code to initialise dummy/test data in the normal releasable code and in general you shouldn't need to know from the main app if you're in a robo run or not.
Now moving past the disclaimer and to actually answer your question... One way you could to this is to have a method in your application class like this
public boolean isRoboTestRun() {
return false;
}
Then create a "TestApplication" in the test package that extends your normal application and overrides this method to return true.
It's hacky, but that's because it's not really meant to work that way :)
At some point you have to init OrmLiteSqliteOpenHelper with your Context.
Let assume you do this in your application class in onCreate. So just create Test<your application class name> in your tests sources and override onCreate with empty implementation.
Robolectric will find this class and will use during the tests. More details here.
I have an android app that uses ORMLite/SQLite and I use Robolectric in conjunction with JUnit 4 to allow me to run unit tests in Android Studio and on a Jenkins build server.
Typically I would setup test data in my tests, in the setup, and then run my test scenarios against it but when I tried to do this I started getting issues and exceptions which seemed to be related to files being locked or something and that seems to be a problem others have had... so what I have done up until now is use the create database method in my database helper to create some dummy data which the tests expect to be there.
The problem is my application now needs to plug into a real database and I can't have it setup dummy data when it runs.
If there a way, within my database helper class, to detect if the code is executing on a device or within Robolectric?
This is what works well for me on Robolectric 3.
public static boolean isRoboUnitTest() {
return "robolectric".equals(Build.FINGERPRINT);
}
To start with, I'll say that you shouldn't be putting code to initialise dummy/test data in the normal releasable code and in general you shouldn't need to know from the main app if you're in a robo run or not.
Now moving past the disclaimer and to actually answer your question... One way you could to this is to have a method in your application class like this
public boolean isRoboTestRun() {
return false;
}
Then create a "TestApplication" in the test package that extends your normal application and overrides this method to return true.
It's hacky, but that's because it's not really meant to work that way :)
At some point you have to init OrmLiteSqliteOpenHelper with your Context.
Let assume you do this in your application class in onCreate. So just create Test<your application class name> in your tests sources and override onCreate with empty implementation.
Robolectric will find this class and will use during the tests. More details here.
I don't know if I'm really rusty with JUnit or their is a concept with Android Testing in particular I'm not familiar with but:
I'm finding it very difficult to understand how my tests get run.
I've created a Test Project based on my main project, and created a class which extends ActivityInstrumentationTestCase2<SinglePaneActivity> and in this Test Case I've implemented setUp(), testPort() and tearDown() methods.
When I run the project as a Android JUnit test it all tests correctly.
However, adding another class extending ServiceTestCase<NativeService> with the same setUp(), testStart() and tearDown() methods implemented, the test isn't performed.
Looking through the documentation I can't find anything which states how the tests are run, I'm assuming since their is no specific setup it done via reflection.
Given that as the case however, I don't understand the documentation on TestSuites or why my Service test case isn't running.
Am I the only one that's finding the usually very well written Android Documentation lacking when it comes to testing?
As #Blackbelt says, the was a warning in the Log's indicating that the Test wasn't running.
My problem was that I had used the constructor auto generated for me by eclipse
public NativeServiceTestCase(Class<NativeService> activityClass) {
And the error was output as a warning in LogCat explaining you need to have an empty argument constructor (But that error wasn't repeated anywhere else with any visibility).