Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to inject a dependency when testing an Android activity without a third-party framework?

I want to test an Android activity CommentActivity that normally constructs and uses an instance of CommentsDataSource (both are classes that I wrote).

public class CommentActivity extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    :
    CommentsDataSource = new CommentsDataSource(..);
    :
  }
  :
}

I'm willing to create MockCommentsDataSource myself and would like to avoid using a third-party mocking framework. (Why? Because I'm a teaching trying to reduce the amount of information I need to cram into the semester and the amount of software my students need to install. I've seen other posts that recommend Guice, roboguice, and Spring.)

My question is how to pass a CommentsDataSource (or MockCommentsDataSource) to the Activity. It doesn't seem practical to make them Serializable or Parcelable, which they would have to be in order to be passed in through the Intent that starts CommentActivity. While I could easily pass in a debug flag, using it would require CommentActivity to know about MockCommentsDataSource, which is really none of its business (and in a separate application):

public class CommentActivity extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    :
    debugMode = getIntent().getBooleanExtra(DEBUG_MODE, false);

    // Get a connection to the database.
    final CommentsDataSource cds = (debugMode ? 
      new MockCommentsDataSource() :   // Abstraction violation
      new CommentsDataSource(this));
      :
   }
   :
}

How should I inject MockCommentsDataSource into CommentActivity? FWIW, I'm using Eclipse and am developing for recent SDK versions.

One solution that occurs to me is to use the abstract factory pattern, since it would be relatively easy to make the factories serializable. Is that the best approach, given my constraints?

like image 387
Ellen Spertus Avatar asked Mar 01 '14 23:03

Ellen Spertus


People also ask

What is dependency injection in Android?

What is dependency injection? Dependency injection (DI) is a technique widely used in programming and well suited to Android development. By following the principles of DI, you lay the groundwork for good app architecture. Implementing dependency injection provides you with the following advantages:

How do I use hilt with Android integration tests?

For integration tests, Hilt injects dependencies as it would in your production code. Testing with Hilt requires no maintenance because Hilt automatically generates a new set of components for each test. To use Hilt in your tests, include the hilt-android-testing dependency in your project: // For Robolectric tests. // ...with Kotlin.

What are the advantages of dependency injection in Java?

Dependency injection provides your app with the following advantages: Reusability of classes and decoupling of dependencies: It's easier to swap out implementations of a dependency. Code reuse is improved because of inversion of control, and classes no longer control how their dependencies are created, but instead work with any configuration.

How do I inject a fake or mock instance of a dependency?

If you need to inject a fake or mock instance of a dependency, you need to tell Hilt not to use the binding that it used in production code and to use a different one instead. To replace a binding, you need to replace the module that contains the binding with a test module that contains the bindings that you want to use in the test.


1 Answers

Here are two ideas:

Not using factory:

This will probably work only for unit tests and not for integration tests:

  1. Create a method that returns CommentsDataSource, e.g. getCommentsDataSource()
  2. Create a class that inherits CommentActivity
  3. Override the getCommentsDataSource() with a method that returns MockCommentsDataSource
  4. Test the new class

Using factory:

As you mentioned, you can change the CommentActivity code to get the CommentsDataSource from a factory method. this way you can have the mock class returned by the factory method.

Hope this helps!

like image 159
Omri374 Avatar answered Sep 22 '22 12:09

Omri374