Today (well, for a year or so), MVP seems to be the bees knees of Android development - or at least everyone talks about it quite a bit. However, quite often people are just as intrigued as they are confused. How do you actually do MVP in Android? What about testing it? In this post, I’ll show you how to whip out an MVP architecture for your app. I’ll even combine it with a touch of TDD - because I just love unit testing!
MVP is an abbreviation of Model-View-Presenter. This is a rather simple architecture: these all three are layers in your application, with well-structured responsibilities.
Model equals data. This layer contains your Java classes for data, as well as
the logic for acquiring it (e.g. fetching from a server or reading from a file).
This layer can also contain some helper methods and utilities, but that’s that -
no other logic here whatsoever.
View is everything you show to your user. This layer should be as thin as
possible: It should be about buttons and labels. When the user interacts with
something on the view, the view shouldn’t “do” anything - it should just pass
Presenter that this thing happened.
Presenter is the core element. When the
View tells the presenter something
happened, the presenter reacts accordingly. For example,
View could tell
presenter that all of UI is now up and running, and
Presenter chooses to
react by downloading a list of blog posts from a server. Meanwhile,
View to show a loading indicator. When the
Model layer is done
fetching the data,
Presenter may manipulate it further to make it more
presentable to the user, and finally invokes
View with the data. The very
last thing in the whole shebang is the
View showing the data to the user.
In “pure” MVP, the
View should not know anything about the
Model, but this
is something that’s a tad debatable. The main idea is to separate the data and
the UI, all the while making things testable.
MVP In Android
The most common way of implementing MVP in Android is to make either activities
or fragments to implement the
View layer. This makes our
View less view-y
than on other platforms since activities and fragments are also responsible
for handling lifecycle events, navigation and so on. However, this is not a
big issue if you are careful.
TDD stands for Test-Driven Development. Basically, it means that you first create a test, make sure it fails, and then write the minimum amount of code that makes the test pass. Then you re-work your test, adding more stuff to it, making it fail again, and then you re-work your code. Rinse and repeat until your feature is done!
Why TDD though? Well, first off, it ensures you write your tests. People always come up with excuses for why they didn’t write tests at all. Second, writing tests beforehand makes you think of the code in such way that makes it testable. Often times when you blindly write your app and try to write the tests afterwards, you face the fact that you simply can’t test the code! It’s too tightly coupled, it’s dependent of a thing that’s not available during testing…
Third and most important thing is that writing tests beforehand ensures your code does what it’s supposed to. Your tests should represent the use case or the business value of what you’re developing, and your code should do just that. You should be coding against the tests, not testing against the code, because in that case you are just validating that your code works, but you don’t verify that it does the right thing. It might even be impossible to verify the code anymore.
TDD + MVP In Android
Combining TDD and MVP in Android means that we’re writing tests first, but
unfortunately we are not going to test everything. We’ll leave the
layer untested for now (since it’s mainly UI testing anyway), and concentrate our
efforts on the presenter instead. The model layer can be tested as needed, depending
of your application. In this example, I’ll use simple POJO (Plain Old Java Object) models
that don’t really need any testing (unless you want to bump the coverage up).
So, let’s start!
First Iteration - Presenter
Let’s begin by creating a new Android project with an empty activity. After you’re done with the wizard, you should be represented by your main activity like this:
Next, we’re going to write the presenter. However, let’s not start by coding -
instead, let’s create the test first! So, create a new class in under the
Now, before writing any tests, you should have a good hunch of what the presenter should be doing. In our example, the view will show a list of items to the user, so the presenter should probably be loading the items and offering them to the view. Great! Let’s write a test for that:
But… We don’t have a
MyPresenter class, not to mention a method in that class.
Which is good! This is our first step in TDD - we have a test that fails. In
TDD, you should be writing tests only as long as you get your first failure.
Missing classes, missing methods, or just a failing unit test are all failures in
Let’s move on and create a new class called
MyPresenter, and create a method
load() there. Now, let’s run our test and ensure that it passes:
Whoo! We just completed our very first cycle of TDD. Now, it’s just iterating
until our feature is complete. From our test’s point-of-view, we don’t care what
load() - it could stay empty for all it cares, as long as it
passes. So, let’s continue on our MVP implementation and think of the presenter
as “done” for now - you’ll soon see why it’s not quite done yet. :)
Second Iteration - View
Okay, let’s start the next iteration. Now we want to test that the view is presented with the data, so let’s pass the view to the presenter as a constructor parameter:
Aaaaand we’re back with the missing class again. We don’t have a
and we don’t even know what type it is! Let’s solve the problem by creating one.
We don’t want to be dependent of the Android platform to run our tests, so let’s
abstract the activity away by using an interface for the view:
Now, let’s create a view for our testing purposes and pass that to the presenter:
We are still getting an error because the presenter doesn’t have a proper constructor yet. Let’s create a constructor that takes the view as a parameter:
We can now run the test and notice that it works, but… How do we ensure that the presenter called the view? We know it didn’t, though, but how can we be sure from the test’s point-of-view?
Third Iteration - Actually Coding Something
We can use the view in our test to ensure that the view was actually called with
actual data. For this, we’ll create a new method in our view interface called
showItems(), which is called by the presenter to present the loaded items on the UI:
Let’s implement this in our test. To ensure that something happens, the view passes the received data back to the test so we can verify it.
Phew, our test just grew quite a bit! Here, our view now implements the one
and only method we have so far. When the presenter calls it, the list of items
is copied to the
itemsToVerify list. After we have called
p.load(), we anticipate
that the view is invoked and the list is copied, so we want to verify the results.
The very last line does exactly just that - it ensures that there are now three
items in the list. Is there? Let’s find out! Run the test again and see for
Surprise! Of course there’s no items, because the view is never invoked! Not to mention the presenter never does anything! Now we finally get to write the presenter!
So, let’s go and write the code that satisfies this test - but remember, don’t write more code than absolutely necessary!
There we go! A simple list of three strings. Re-run the test and you should see the test passed. Nice job!
You might be wondering now: “What about the model? Where’s that?” In our example
here, the whole model layer consists of the
String class. Basically, the layer
doesn’t even exist for now. Hmm… Hold on. How do we ensure the items we got
passed to the view are the correct ones when the presenter is the only one
who knows about them?
Fourth Iteration - Models
The answer is, we’ll implement our model layer. The model layer offers the items
to the presenter layer, so quite obviously we start by passing another constructor
parameter, just like in the case of the view. Let’s call our model layer
Just like with the view, we’ll also create an interface for this. To save some time, let’s also add the method to fetch the items here already:
Back to the test: Let’s create an object to represent our service and implement the interface. We will feed the service with a test list of items.
One more thing to fix: Change the constructor of the presenter to accept two arguments:
To re-cap, the whole test now looks like this:
You can run this test and you’ll see that it works just fine! Now, let’s add
three more assertions to the end of it to see that we really get the three strings
C our service returns.
Now we run the test, and… Uh oh:
Hold on, our presenter doesn’t yet ask the service for the items! Let’s change that:
Ta-dah! Your test should be passing now. Now we can do end-to-end verification through our MVP: The view invokes presenter, presenter fetches data from the model layer, and passes it to the view. And we haven’t even written any Android stuff yet!
Bring in the Android!
Now we have some fully tested code powering up our MVP, so we can go and wire it up in our activity. First off, let’s make a crude UI that hold a button and three text views. The idea is that when the user taps the button, the presenter will fetch the three strings and pass them back to the view, which will then populate the text views using them.
So, open the
activity_main.xml layout and make it look like below. Note that
the root element is a
Next, open the
MainActivity class and bind the views to fields:
You can launch your app at this point, and you should see a button with three
text views under it. Nothing happens when you click the button, though, and we
don’t have the MVP in place just yet. Let’s fix that! First, let’s finalize our
view layer by making the activity implement the
Now just three more things: First, let’s create a new, concrete service class that pretty much does just the same thing as the one we wrote in the test:
Second, create the presenter in the activity:
And for the grand finale, let’s make the button to actually call the presenter:
AND WE ARE DONE! Let’s take the app for a spin. After you launch the app, you should see this:
And when you click the button, you should see the magic happen:
Doing MVP in Android is nothing difficult, just like TDD is not difficult. However, both (and especially TDD) require a certain change in your mindset if you’re not used to them.
With TDD, you end up with highly tested code and you become more confident about it. When you write your code in an MVP manner, your code is well structured and, most importantly, it’s testable. Together, these two provide you with a stable framework to build your app upon.
As always, if you found this post helpful or if you learned something and want to thank me, consider buying me a cup of coffee. It fuels my coding and makes me want to write more posts. :) Until next time!