IsolatedContext vs. AndroidTestCase.getContext() - android

I'm writing some tests to test my sqllite database code. Can someone here explain if there would be a difference writing those tests using the context I get from AndroidTestCase.getContext() or using an IsolatedContext.

For those that don't want to follow the link to the Google Group, here is the answer given there:
AndroidTestCase.getContext() returns a normal Context object. It's the
Context of the test case, not the component under test.
IsolatedContext returns a "mock" Context. I put "mock" in quotes
because its not a mock in the normal sense of that term (for testing).
Instead, it's a template Context that you have to set up yourself. It
"isolates" you from the running Android system, so that your Context
or your test doesn't accidentally get outside of the test fixture. For
example, an IsolatedContext won't accidentally hit a production
database (unless you set it up to do that!) Note, however, that some
of the methods in an IsolatedContext may throw exceptions.
IsolatedContext is documented in the Developer Guide under Framework
Topics > Testing, both in Testing Fundamentals and in Content Provider
Testing.
Here is the Android docs on IsolatedContext.
And here is the relevant section of the Testing Fundamentals document.

The answer:
http://groups.google.com/group/android-developers/browse_thread/thread/3a7bbc78258a194a?tvc=2

I had the simple problem: I need to test my DAO class without touching the real database. So I found the IsolatedContext from docs. But finally I found the other context in the same docs: RenamingDelegatingContext might be more easier to use. Here is my test case:
public class AddictionDAOTest extends AndroidTestCase {
#Override
public void setUp() throws Exception {
super.setUp();
setContext(new RenamingDelegatingContext(getContext(), "test_"));
}
public void testReadAllAddictions() throws Exception {
ImQuitDAO imQuitDAO = new ImQuitDAO(getContext());
...
}
}

Related

How to write junit test for after getting response in Android

I have this below code.I want to write junit test for this method.
#Override
public void getSuccessData(Response response) {
if(response.getStatus().equalsIgnoreCase("success")){
BaseApplication.getInstance().setAccessToken(response.getToken().getAccessToken());
commonNavigate.navigateToHomeScreen((HomeActivity)view);
}
}
How can i write junit test case for this method.I am very new to junit.
This is (most probably) a callback method you want to test.
If you want to test a callback, you would need to understand mocking.
In very basic terms, mocking lets you create a fake source object and invoke some request method on it, and then verify that a particular callback has been invoked with certain parameters. Read about Mockito, which can be easily integrated with Android Studio: http://site.mockito.org/
Secondly, you code calls android-specific code:
BaseApplication.getInstance().setAccessToken(response.getToken().getAccessToken());
commonNavigate.navigateToHomeScreen((HomeActivity)view);
This code has dependency upon Context object. Please read what Context object means in Android and how it is shared in Application/Activity/View classes. "navigateToHomeScreen" method surely needs a Context!
Either you will mock android dependencies with fake objects, or you could run Instrumented tests which provide Context and other Android-framework-defendant objects.
To sum up - these are wide and complex topics and you should make a research on them first.
Use Mockito framework if you want to test methods. You need to mock objects so that you can test the method with dummy response.
Please refer this link for mockito
https://developer.android.com/training/testing/unit-testing/local-unit-tests.html#setup

Inheritance of TestCases on Android

I was wondering if it was good practice to subclass the test cases on Android. I mean, I need to test a lot of Parcelable objects and I could create a class like GenerericParcelableAndroidTestCase to test all these objects.
I also have a problem implementing it, I have something like this:
public class GenericParcelableTest extends AndroidTestCase {
private Parcelable p = null;
GenericParcelableTest(Parcelable p) {
this.p = p;
}
public void testDescribeContents() throws Exception {
assertEquals(0, p.describeContents());
}
}
And that:
public class AttachmentTest extends GenericParcelableTest {
public AttachmentTest() {
super(new Attachment());
}
}
Attachment implements Parcelable of course.
It returns me this error:
junit.framework.AssertionFailedError: Class GenericParcelableTest has no public constructor TestCase(String name) or TestCase()
I mean, I know that I created no empty constructor but why would I need one?
And generally, is there some known issues with this approach? If not why is there very few article on this topic on the internet (and actually some say even that it's not a good idea).
I have this conversation quite often when introducing new team members to unit testing. The way I explain it is by stating that your tests are first class citizens of your code base (no pun intended), they are susceptible to the same technical debt as any other part of your code base and have equivalent (maybe more?!) importance as that of the runtime code.
With this mindset, the questions begins to answer itself; if it makes sense from an OO perspective to use inheritance (i.e. your subclass is a insert name of test superclass) then subclass away. However, like any abuse of inheritance ever, be careful...the minute you add a test case that doesn't rely upon that superclass behaviour you may have a code smell.
In this scenario, it's likely (perhaps 90% of the time?) it is a separation of concern issue within the code being placed under test, i.e. the "unit" under test isn't actually (one) unit but has combinatorial behaviour. Refactoring that code to do one thing would be a good way of allowing your super-class test case to live on. However, watch this super class test case like a hawk...the minute you see booleans being added to signatures to "allow that similar but not the same" test case to run under your once unpolluted super class then you have a problem, a tech debt problem that is no different to your runtime code.
At last check AndroidTestCase depends on an Activity context so it's likely best described as an integration test which tend to regularly have boilerplate super-class test behaviour. In this case, try to narrow the focus of your superclass to the use case under test...i.e. extends LoginUseCase or extends LoginScenario to better "bucket" those subclasses in the first instance. This will help guide would be extenders as to whether they should be using it for their non-login scenario. Hopefully, conversation will ensue and tech debt accumulation be avoided!
Regarding your error, in JUnit3 do what #Allen recommends, if moving to JUnit4 with something like Robolectric then explore using Rules as well as #BeforeClass.
Personal note
I have only felt the need to write test super classes for pseudo-unit tests that mock an API end point (akin to MockWebServer if you are familiar with that product) and DAO integration tests whereby an in-memory db is started and torn down over the lifecycle of each test (warning - slow (but useful) tests!)
junit.framework.AssertionFailedError: Class GenericParcelableTest has no public constructor TestCase(String name) or TestCase()
You get this error because JUnit needs to be able to construct an instance of your test class. It only knows how to do this using no-arg, or single string constructors.
Instead of performing initialization in your constructor, you should put it in the setUp() method. This will let you use the default constructor while still initializing the object before the test method is called.

Android JUnit4 Testing - Where to get Context from?

I have to build an app with sqlite usage. Now I want to write my unit tests. These unit tests should test my class SQLiteBridge. SQLiteBridge provides DAOs for every child class of Model.
Now I got the problem that I need a context to create my SQLiteBridge. SQLiteBridge creates and handles a SQLite database on the system..
Where to get the Context-Object from?
My setup is like here (so I'm using Junit4 [thanks god]):
http://tools.android.com/tech-docs/unit-testing-support
EDIT: I hope there is a way like the old AndroidTestCase to extend without losing Junit4. :)
As described here: https://code.google.com/p/android-test-kit/wiki/AndroidJUnitRunnerUserGuide
Use the InstrumentationRegistry to obtain the context.
However if you call InstrumentationRegistry.getContext() directly you may get an exception opening your database. I believe this is because the context returned by getContext() points to the instrumentation's context rather than that of your application / unit test. Instead use InstrumentationRegistry.getInstrumentation().getTargetContext()
For example:
#RunWith(AndroidJUnit4.class)
public class SqliteTest {
Context mMockContext;
#Before
public void setUp() {
mMockContext = new RenamingDelegatingContext(InstrumentationRegistry.getTargetContext(), "test_");
}
}
The RenamingDelegatingContext simply prefixes the file/database names with test_ to prevent you from overwriting data that you may have in the same simulator.
jUnit 4 (and perhaps other versions of jUnit) and androidx use:
ApplicationProvider.getApplicationContext();
See: Android Documentation

Trying to mock Environment.getExternalStorageState

I've been trying to figure out for some hours how to mock the call to Environment.getExternalStorateState() while unit testing my Android App.
I've been able to mock SystemServices, Providers and Services, but I cannot work out how to mock this call, as it is not a call to something provided within my context, but something in the OS environment.
Would be grateful about some help.
You could write helper around this call and easily mock it after (sorry for having helper part in class name):
public class EnvironmentHelper {
public String getStorageState() {
return Environment.getExternalStorateState();
}
}
Or if you use Robolectric you could call:
ShadowEnvironment.setExternalStorageState(Environment.MEDIA_MOUNTED);
It depends on your setup and needs but I would recommend to invest in Robolectric usage
I just worked around wrapping the call to the Environment method in my test helper class so I could mock the status of the SD Card as I wanted depending on a variable I could set as desired in each test case.
Best solution I think.

Android unit testing and interfaces

I have been having quite a bit of trouble implementing unit testing on the Android. As a simple test, I've been trying to match a string retrieved from string resources:
String myString = myActivity.getResources().getString(R.string.testString));
However, when unit testing this invariably results in a null pointer exception. This includes robolectric as well as the Junit implementation delivered with the Android sdk.
One possible solution is to approach the retrieval of resources in a manner similar to a data access object. That is, create an interface through which string resources would be accessed. This would allow me to mock access the string resource. Similarly, I could separate the non-android dependent behavior of, say, an Activity, into a separate pojo class. This would allow me to run unit tests using standard Java testing tools. In fact, I could potentially delegate any Android infrastructure related activity to an interface.
This seems like a lot of jumping through hoops to get to unit testing. Is it worth it? Is there a more viable approach?
It turned out, the problem was that the activity has to be gotten in the actual test method. So, for example, my method now looks like this:
public void testGetActivityResourceString() {
Activity myActivity = this.getActivity();
String myString = myActivity.getResources().getString(R.string.hello);
Assert.assertNotNull(myString);
}
Whereas before I was creating activity in setup. This giveaway was in the docs:
"For each test method invocation, the Activity will not actually be created until the first time this method is called."
This was a real hassle to figure out. The example for HelloWorldTest doesn't work for the same reason.
Here's the full entry:
Public T getActivity ()
Since: API Level 3
Get the Activity under test, starting it if necessary.
For each test method invocation, the Activity will not actually be created until the first time this method is called.
If you wish to provide custom setup values to your Activity, you may call setActivityIntent(Intent) and/or setActivityInitialTouchMode(boolean) before your first call to getActivity(). Calling them after your Activity has started will have no effect.
NOTE: Activities under test may not be started from within the UI thread. If your test method is annotated with UiThreadTest, then your Activity will be started automatically just before your test method is run. You still call this method in order to get the Activity under test.
This works correctly:
public void testGetResourceString() {
assertNotNull(mActivity.getResources()
.getString(com.example.pkg.R.string.testString));
}
Because you haven't provided any of your code but only the getReousrces() line, I will guess what you are doing wrong:
you are not using the correct base class for your test, use ActivityInstrumentationTestCase2 because you need the system infrastructure
you are using the resources of your test project instead of your project under test, that's why in my example the id is com.example.pkg.R.string.testString.

Categories

Resources