Model View Presenter (MVP) in Android, Part 3

You may also like...

9 Responses

  1. Carlos says:

    Very good serie about this topic,clear explanations and good examples

  2. DanV says:

    Hi,
    In this case the presenter is responsible to get instances of all his model dependencies which makes it harder to write tests, especially unit tests.
    There are many examples which state the the View should pass all dependencies to the Presenter.
    On one hand it defies the MVP rule and makes the view aware of the models but on the other it helps you to pass mocked models to the Presenter and thus makes easier to test.
    Since i didn’t see any tests in your Git project i would love to hear your opinion on this issue.

    • tinmegali@gmail.com says:

      Hello DanV,
      First of all, thanks for the feedback!

      My bad, I should really add some test in the git. I’ll update the git with a test for reference.
      Although, I can’t see the difficulty that you mentioned.
      Yes, the Model instance is really created by the Presenter, but by my understanding this doesn’t mess up the tests.
      I mean, if you use Mockito, you can test it just fine.
      Take a look at that snippet.

      @RunWith(RobolectricGradleTestRunner.class)
      @Config(constants = BuildConfig.class, sdk = 21, manifest = "/src/main/AndroidManifest.xml")
      public class ModelTest {
          private MainPresenter mPresenter;
          private MainModel mModel;
      
          @Before
          public void setup(){
              mPresenter = mock(MainPresenter.class, CALLS_REAL_METHODS);
              mModel = mock(MainModel.class, CALLS_REAL_METHODS);
      
              when(mModel.getPresenter()).thenReturn(mPresenter);
              when(mPresenter.getModel()).thenReturn(mModel);
          }
      
          @Test
          public void simpleTest(){
              String name = "simple_mvp";
              // Add name
              MVP_MainActivity.ProvidedPresenterOps presenterOps = mPresenter;
              presenterOps.clickSaveName(name);
              verify(mPresenter.getModel(), atLeastOnce()).saveName(anyString());
              verify(mPresenter).onNameSaved(name);
      
              // Clear name
              presenterOps.clickClearName();
              verify(mPresenter.getModel(), atLeastOnce()).clearName();
              verify(mPresenter).onNameCleared();
          }
      }
      

      You could create the Model and the Presenter in the View and then pass the Model reference to the Presenter, but I don’t see why this would be necessary.
      If you see a specific situation where my implementation could be a problem, please share with me and we can discuss more about.
      Thanks for the input.

      • DanV says:

        Hi,
        Thank you for the quick answer.

        Please take a look at Mockito.CALLS_REAL_METHODS JavaDoc.
        It states that it is not a good practice to use this method “* However, there are rare cases when partial mocks come handy:
        * dealing with code you cannot change easily (3rd party interfaces, interim refactoring of legacy code etc.)
        * However, I wouldn’t use partial mocks for new, test-driven & well-designed code.”

        However, it is not my problem.
        i would like to test the presenter as a standalone unit using unit tests (not instrumentation)
        my specific problem is that i have a static class DependencyInjector that provides the models to the entire app.
        DependencyInjector.getsCrashReporter(), DependencyInjector.getDirectionsManager() and so on..
        Is it a good practice to set mocked models in the DependencyInjector and how do i ensure that the DependencyInjector restarted properly after each test?

        Thank you!

        • tinmegali@gmail.com says:

          Hello again DanV,
          I’m aware about this alert in Mockito docs, I chose to use it for simplicity. But it is completely possible to test Presenter and Model with JUnit without a problem, unless the method tested needs to access Model, in that case you’ll need to provide some kind of mock.

          I don’t know exactly what DependencyInjector you’re using, but as far as Dagger goes, static injection isn’t a good practice, especially when it comes to testing.

          Warning: This feature should be used sparingly because static dependencies are difficult to test and reuse.

          Taken from Dagger docs

          That said, I don’t know if the practice that you mentioned is a good one, but who am I to tell? lol
          Take a look at this article, it a good guide to test depedency injection using Roboeletric. I tend to use RoboEletric in my tests, because it provides a framework with a lot of Android classes mocked.

          I didn’t use Dependency Injection on simple-mvp to maintain the library without any external influences other than Android SDK and Java. Some could argue that adding DI would make it more productive and maybe they’re right. But my main goal in this series and on the library was to illustrate MVP concept, hence the code doesn’t use any external libs.

          Maybe this discussion concerning DI is a little bit offtopic. I fear that it could confuse somebody out there. I’m available if you need to discuss more, but can you be so kind to send an email to tinmegali@gmail.com with further questions? I’ll answer as soon as I can.
          Tks again for the input!

  3. Vasiliy says:

    Very good tutorial. I especially like the clear diagrams.
    That said, IMHO, activities should not be views in Android’s MVP. It leads to a lot of “tricks” and “workarounds” that wouldn’t be required if we would designate activity as presenter.
    I summarized my thoughts on the subject here: http://www.techyourchance.com/mvp-mvc-android-1/

  4. Ahmed al-sabsab says:

    Very good tutorials thanks a lot.
    So you don’t recommend us to use this framework for production purpose?

    • tinmegali@gmail.com says:

      Hello Ahmed, Sorry for the late response. I’m being so busy lately that I couldn’t pay much attention to my blog.
      Concerning your doubt. I don’t see any problem in using the framework for productions, however, there are better ways to do it. If you add “Dependency Injection” for example, it would improve a lot.

Leave a Reply

Your email address will not be published. Required fields are marked *