Testing Android Blocks That Need Context

I am writing my first Android-based backend, and I am trying to create a unit test creating my database.

Currently, the problem I am facing is getting a valid Context object to pass my SQLiteOpenHelper implementation to. Is there a way to get a Context object in a class extending TestCase? The solution I was thinking about is to create an Activity instance in the setup method of my TestCase, and then assign the context of this action to a field variable that my test methods can access ... but there seems to be an easier way.

Thanks for your input!

Macy

+57
android database unit-testing
Jan 19 '10 at 17:54
source share
9 answers

You can try switching to AndroidTestCase . From looking at the docs, it seems like it should provide you with a valid context for navigating to SQLiteOpenHelper.

Edit: Keep in mind that you may have to set up your tests in the โ€œAndroid Test Projectโ€ in Eclipse, as the tests will try to run on the emulator (or on a real device).

+40
Jan 19 '10 at 18:01
source share
โ€” -

You can use InstrumentationRegistry methods to get the context:

InstrumentationRegistry.getTargetContext() - Provides the Context application of the target application.

InstrumentationRegistry.getContext() - Provides the Context this Toolbox.




For AndroidX, use InstrumentationRegistry.getInstrumentation().getTargetContext() or InstrumentationRegistry.getInstrumentation().getContext() .

+26
May 20 '16 at 16:20
source share

Using the AndroidTestCase:getContext() method gives only my context. For my tests, I use empty activity in my main application and get Context through this. I am also extending the test suite class with the ActivityInstrumentationTestCase2 class. Seems to work for me.

 public class DatabaseTest extends ActivityInstrumentationTestCase2<EmptyActivity> EmptyActivity activity; Context mContext = null; ... @Before public void setUp() { activity = getActivity(); mContext = activity; } ... //tests to follow } 

What do everyone else do?

+5
Aug 20 2018-12-12T00:
source share

You must use ApplicationTestCase or ServiceTestCase.

+3
Jan 19 '10 at 21:01
source share

You can get the MockContext and return, for example, MockResources to getResources() , a valid ContentResolver to getContentResolver() , etc. This allows, with some pain, some unit tests.

An alternative is to launch, for example, Robolectric , which simulates an entire Android OS. This will be for system tests: it runs much slower.

+3
Jun 04
source share

Extending AndroidTestCase and calling AndroidTestCase: getContext () works fine for me to get the context and use it with SQLiteDatabase.

The only thing that the database creates and / or uses will be the same as the one used by the production application, so you probably want to use a different file name for

eg.

  public static final String NOTES_DB = "notestore.db"; public static final String DEBUG_NOTES_DB = "DEBUG_notestore.db"; 
+2
May 04 '13 at 2:57
source share

First create a test class in (androidTest).

Now use the following code:

 public class YourDBTest extends InstrumentationTestCase { private DBContracts.DatabaseHelper db; private RenamingDelegatingContext context; @Override public void setUp() throws Exception { super.setUp(); context = new RenamingDelegatingContext(getInstrumentation().getTargetContext(), "test_"); db = new DBContracts.DatabaseHelper(context); } @Override public void tearDown() throws Exception { db.close(); super.tearDown(); } @Test public void test1() throws Exception { // here is your context context = context; }} 
0
Sep 12 '16 at 9:30
source share

Your test is not a unit test !!!

When you need

  • context
  • Read or write for storage
  • Access network
  • Or change any config to test your function

You do not write unit test.

You need to write your test in the androidTest package

0
Jun 09 '19 at 12:03 on
source share

An alternative solution is to avoid using ApplicationTestCase or AndroidTestCase or any other class that depends on Context . The fact is that there is no need to test the SQLite or ORM structure so that you can create an interface using the basic CRUD methods:

 public interface UsersManager{ User createUser(String userId); User getUser(String userId); boolean updateUser(User user); boolean deleteUser(User user); } 

And implement two versions: one for the tests and the other for the production version. The test version can be easily implemented using the HashMap :

 public class TestUsersManager implements UsersManager{ private HashMap<String, User> users = new HashMap(); public User createUser(String userId){ User result = new User(userId); users.put(userId, user); return result; } //... other methods } 

It works fast (without an IO disk in the case of SQLite ) and has no external dependencies. By the way, this is also an additional level of abstraction: for production code, you can easily switch between ORM frames.

-one
Feb 04 '16 at 16:11
source share



All Articles