Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Tomek Kaczanowski - Practical Unit Testing with JUnit and Mockito - 2013.pdf
Скачиваний:
228
Добавлен:
07.03.2016
Размер:
6.59 Mб
Скачать

Chapter 5. Mocks, Stubs, Test Spies

Listing 5.6. myFerrari throws an exception

public class MockitoThrowingExceptionsTest {

private Car myFerrari = mock(Car.class);

@Test(expected = RuntimeException.class) public void throwException() {

when(myFerrari.needsFuel())

.thenThrow(new RuntimeException()); myFerrari.needsFuel();

}

}

The test passes, because myFerrari throws the expected exception as instructed. Expectations set.

This test also passes, as myFerrari obediently throws an exception when its needsFuel() method is executed.

You need to use a different syntax when setting expectations on void methods. This is discussed in Section 6.5.

5.1.3. Verification

Now we know that using Mockito, we can tell our test double to return some values that are required by our tests. This is great, and we will be making use of this knowledge very soon. However, for testing purposes we need something more. We want to make sure that the SUT has executed certain methods of the DOCs (represented by test doubles). To do this we need to also verify whether some methods of test doubles have been called. Or, to put it differently, we want to verify the indirect outputs of the SUT.

Watch out now, because this is the moment we enter the world of interactions testing for real! Up till now, our tests have only mentioned other collaborators. Expectations could be construed along the lines of "if a certain call to the collaborator happens, then this collaborator should do X or Y". Now things are different. We are starting to demand that certain methods of collaborators are executed. This makes our tests very much linked to the production code, which in turn spells trouble, as it makes them fragile - if the implementation of the SUT changes, our tests will need to be rewritten. The rule of thumb to follow here is: write an interactions test only if some of the SUT’s features cannot be tested using state testing.

The first example, shown in Listing 5.7, presents a successful attempt at verification of a test double’s behaviour. First it invokes some of the methods of myFerrari, then it verifies whether they have been called. A different, static method of the org.mockito.Mockito class, called verify(), is used to check the behaviour of myFerrari. The test in Listing 5.7 passes, because the requested methods have really been invoked.

68

Chapter 5. Mocks, Stubs, Test Spies

Listing 5.7. Expectations met, verification passed

public class MockitoVerificationTest {

private Car myFerrari = mock(Car.class);

@Test

public void testVerification() { myFerrari.driveTo("Sweet home Alabama"); myFerrari.needsFuel();

verify(myFerrari).driveTo("Sweet home Alabama"); verify(myFerrari).needsFuel();

}

}

Calling the methods of the test double. Nothing fancy here: no Mockito syntax of any sort, simply normal method calls

The verification part. Checking has occurred of whether myFerrari has really been asked to drive to Alabama, and whether someone has requested it to answer a "Do you need fuel?" question.

Once again the code is quite readable: "verify() that myFerrari was asked to drive() to Alabama".

Now let us take a look at another example. This time the expectations are not met. The test is shown in Listing 5.8.

Listing 5.8. Different methods executed than expected

public class MockitoFailedVerificationTest {

private Car myFerrari = mock(Car.class);

@Test

public void testVerificationFailure() { myFerrari.needsFuel();

verify(myFerrari).getEngineTemperature();

}

}

The needsFuel() method of a test double of type Car was called,

…but invocation of getEngineTemperature() is what had been expected! This cannot possibly work and will surely fail.

…and fail it does, as displayed below.

Listing 5.9. The output of a failed verification test

Wanted but not invoked:

car.getEngineTemperature();

-> at com.practicalunittesting.MockitoFailedVerificationTest

.testVerificationFailure(MockitoFailedVerificationTest.java:22)

However, there were other interactions with this mock:

-> at com.practicalunittesting.MockitoFailedVerificationTest

.testVerificationFailure(MockitoFailedVerificationTest.java:21)

the getEngineTemperature() method had been expected, but did not occur. Hence the failure.

69

Chapter 5. Mocks, Stubs, Test Spies

Mockito informs us, that some other methods of myFerrari were invoked. This might be a good debugging hint.

The error message is quite clear. Mockito also provides detailed information on code lines, so finding the problem is rather simple.

The next listing - Listing 5.10 - presents another situation where expectations are not fulfilled. It illustrates the fact that Mockito not only can verify methods which have been invoked, but is also sensitive to the parameters passed.

Listing 5.10. Method invoked with different parameters than expected

public class MockitoFailedVerificationArgumentsTest {

private Car myFerrari = mock(Car.class);

@Test

public void testVerificationFailureArguments() { myFerrari.driveTo("Sweet home Alabama"); verify(myFerrari).driveTo("Sweet home Honolulu");

}

}

myFerrari headed towards Alabama …but we wanted to get to Honolulu!

Once again the error message is very clear.

Listing 5.11. The output of failed verification test - arguments do not match

Argument(s) are different! Wanted: car.driveTo("Sweet home Honolulu");

-> at com.practicalunittesting.FailedVerificationArgumentsTest

.testVerificationFailureArguments(FailedVerificationArgumentsTest.java:22) Actual invocation has different arguments:

car.driveTo("Sweet home Alabama");

-> at com.practicalunittesting.FailedVerificationArgumentsTest

.testVerificationFailureArguments(FailedVerificationArgumentsTest.java:21)

Expected

:car.driveTo("Sweet

home

Honolulu");

Actual

:car.driveTo("Sweet

home

Alabama");

Readable error messages are one of the selling points of Mockito. This feature is really important!

5.1.4. Conclusions

So far we have looked at a bit of Mockito, and we know that it can help us to write tests with test doubles. In particular, Mockito can:

• create various test doubles (e.g. Car myFerrari = Mockito.mock(Car.class)),

• …which by default return some canned values (e.g. assertFalse(myFerrari.needsFuel())),

70

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]