Reputation: 26661
Can you please explain how I can get test coverage? I'm looking for help because Mockito is totally counter-intuitive. If I use only mock objects, then how could I ever get test coverage? I don't understand.
Here are my tests.
package dev.game.adventure;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.CoreMatchers.*;
import static org.mockito.Mockito.*;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.widget.TextView;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class AdventureTest {
private static final String FAKE_STRING = "HELLO WORLD";
@Mock
Simulation engine;
@Mock
AdventureWorld mWorld;
@Mock
Adventure mworld;
@Mock
Context aContext;
@Mock
FullscreenActivity mActivity;
@Mock
Drawable mDrawable;
@Mock
Resources mResources;
@Mock
Place mPlace;
@Mock
AdventureGame ag;
@Test
@Ignore
public void Tedye() {
//when(mWorld.defaultPlace()).thenReturn(mPlace);
// myObjectUnderTest.wakeMeAfter(new WalkingPerson(myObjectUnderTest, mWorld, "new", 2, mActivity), 10);
//String result2 = myObjectUnderTest.getHelloWorldString();
//assertThat(result2, is(FAKE_STRING));} createPlace("Heaven", target, R.mipmap.dungeon2);
// Adventure a = new Adventure(textview, mactivity, ag);
}
@Test
@Ignore
public void testd() {
// Textview scrollable = ''''''''''''(R.id.textView1);
when(mWorld.defaultPlace()).thenReturn(mPlace);
Context mCont;
}
@Test
@Ignore
public void adventureWorld() {
// Simulation myObjecUnderTest = new Simulation();
Adventure a = new Adventure(new TextView(aContext), mActivity, ag);
Player p = a.getPlayer();
p.say("foobar", mActivity);
p.say("Hello my name is " + a.getPlayer().getMe().name, mActivity);
}
//@Ignore
@Test
public void adventureTest() {
Simulation myObjectUnderTest = new Simulation();
when(mWorld.defaultPlace()).thenReturn(mPlace);
myObjectUnderTest.wakeMeAfter(new WalkingPerson(myObjectUnderTest, mWorld, "new", 2, mActivity), 10);
String result2 = myObjectUnderTest.getHelloWorldString();
assertThat(result2, is(FAKE_STRING));
}
//@Ignore
@Test
public void personTest() {
Simulation myObjectUnderTest = new Simulation();
when(mResources.getDrawable(R.mipmap.dungeon)).thenReturn(mDrawable);
when(mActivity.getResources()).thenReturn(mResources);
when(mActivity.getResources().getDrawable(R.mipmap.dungeon)).thenReturn(mDrawable);
when(mWorld.defaultPlace()).thenReturn(mPlace);
WalkingPerson myObjectUnderTest2 = new WalkingPerson(myObjectUnderTest, mWorld, "blaha", 2, mActivity);
String result2 = myObjectUnderTest2.getHelloWorldString();
myObjectUnderTest2.getThings();
myObjectUnderTest2.getWorld();
assertThat(result2, is(FAKE_STRING));
}
//@Ignore
@Test
public void trollTest() {
Simulation myObjectUnderTest = new Simulation();
AdventureWorld ag;
when(mResources.getDrawable(R.mipmap.dungeon)).thenReturn(mDrawable);
when(mActivity.getResources()).thenReturn(mResources);
when(mActivity.getResources().getDrawable(R.mipmap.dungeon)).thenReturn(mDrawable);
when(mWorld.defaultPlace()).thenReturn(mPlace);
WalkingPerson myObjectUnderTest2 = new Troll(myObjectUnderTest, mWorld, "Loki", mActivity);
String result2 = myObjectUnderTest2.getHelloWorldString();
myObjectUnderTest2.getThings();
AdventureWorld adv = (AdventureWorld) myObjectUnderTest2.getWorld();
//assertThat(adv.defaultPlace().toString().equals(mWorld.defaultPlace().toString()));
// assertThat(adv.defaultPlace(), is(FAKE_STRING));
assertThat(myObjectUnderTest2.getName(), is("Loki"));
//assertThat(adv.messsage, is(FAKE_STRING));
}
//@Ignore
@Test
public void cokeTest() {
when(mWorld.getPlace("Dungeon")).thenReturn(mPlace);
mWorld.getPlace("Dungeon").addThing(new CocaCola("Ljummen cola"));
Simulation myObjectUnderTest = new Simulation();
when(mResources.getDrawable(R.mipmap.dungeon)).thenReturn(mDrawable);
when(mActivity.getResources()).thenReturn(mResources);
when(mActivity.getResources().getDrawable(R.mipmap.dungeon)).thenReturn(mDrawable);
when(mWorld.defaultPlace()).thenReturn(mPlace);
WalkingPerson myObjectUnderTest2 = new Troll(myObjectUnderTest, mWorld, "blaha", mActivity);
String result2 = myObjectUnderTest2.getHelloWorldString();
myObjectUnderTest2.getThings();
myObjectUnderTest2.getWorld();
assertThat(result2, is(FAKE_STRING));
}
@Ignore
@Test
public void testPlace() {
Simulation myObjectUnderTest = new Simulation();
when(mResources.getDrawable(R.mipmap.dungeon)).thenReturn(mDrawable);
mWorld.createPlace("Heaven", mActivity, R.mipmap.dungeon2);
mWorld.createPlace("Hell", mActivity, R.mipmap.dungeon2);
mWorld.connect("Heaven", "Hell", "Down", "Up");
mWorld.randomPlace();
assertTrue(false);
}
@Ignore
@Test
public void useAppContext() throws Exception {
// Context of the app under test.
// Context appContext = InstrumentationRegistry.getTargetContext();
// assertEquals("dev.game.adventure", appContext.getPackageName());
}
}
The repository is available online.
Upvotes: 1
Views: 1207
Reputation: 2432
I took a shot at writing a quick example of how a mock can be applied to help with unit tests. Hopefully this can help clear things up.
In this example, I have two primary classes named SampleClass
and Validator
, with the idea being that SampleClass
relies on an instance of Validator
to help perform its actions.
SampleClass:
//This class's only function is to return one string if the username it's given is valid, and another string if its not valid. It does this with the help of the Validator class
public class SampleClass {
private final Validator validator;
public SampleClass(Validator v){
this.validator = v;
}
public String createWelcomeMessage(final String username){
if(this.validator.isValid(username)){
return "Welcome, " + username + "!";
}
return username + " is not a valid username.";
}
}
Validator:
//This class's only job is to validate strings. Right now, all it does is check the length, and fail if its > 15 characters.
public class Validator {
public boolean isValid(final String str) {
if(str.length() > 15){
return false;
}
return true;
}
}
So let's say I want to write some unit tests for SampleClass
. Unit tests should typically be testing small, focused units of code, and I don't want the specific details of Validator
to bleed into these tests. I really just care about how the Validator
class's output affects SampleClass
, and the functionality that SampleClass
implements. This is where mocking(and Mockito) comes in, as I can mock the interactions with Validator
to test the behavior of SampleClass
in isolation.
SampleClassTest:
public class SampleClassTest {
//Mock the validator class, which SampleClass depends on.
private Validator validator = Mockito.mock(Validator.class);
//Do not mock the SampleClass class. Create a new one, and use the mocked validator within it.
private SampleClass sampleClass = new SampleClass(validator);
//Test that a valid username will print out the message "Welcome, username!"
@Test
public void testValidUsername(){
Mockito.when(validator.isValid(Mockito.anyString())).thenReturn(true);
final String message = this.sampleClass.createWelcomeMessage("testuser");
Assert.assertEquals("Welcome, testuser!", message);
}
//Test that an invalid username will print out the message "username is not a valid username"
@Test
public void testInvalidUsername(){
Mockito.when(validator.isValid(Mockito.anyString())).thenReturn(false);
final String message = this.sampleClass.createWelcomeMessage("thisiswaywaywaytoolong");
Assert.assertEquals("thisiswaywaywaytoolong is not a valid username.", message);
}
}
Using jacoco to look at unit test coverage, SampleClass
is fully covered, and Validator
is completely uncovered because right now it's mocked and untested. I should write additional unit tests focused on Validator
(unmocked!) in isolation.
Applying it to your project:
For an example, consider the go method on your Person class. It seems like you could write some unit tests for this method and use Mocks for the FullscreenActivity
and World
objects, and verify that the method correctly manipulates the World
object under various conditions. That would cover Person->go
with some unit tests, and do so in a way where the Person
tests are isolated from your other classes. This can also be very useful when dealing with Android widgets and such (as CommonsWare mentioned), since you can just mock it, instead of dealing with a complex or otherwise impractical class in your tests.
TL;DR
Upvotes: 1