Добавил:
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

I would only suggest writing some Javadocs: namely, for the RaceResultsService class, as this is the crucial part of the code (from the business point of view)8.

5.4.2. The Second Test: Send a Message to Multiple Subscribers

The decision concerning which test to perform next comes naturally: since I know that a message has been sent to one single client, I now wish to test whether this functionality will also work for more than one subscriber. The test is shown in Listing 5.25.

I created the second test method (allSubscribedClientsShouldRecieveMessages()) by

copying the content of the first test method (subscribedClientShouldReceiveMessage()). Then I introduced some changes there. Copy & paste technique is potentially dangerous, so I must double-check that the test does what I intended it to do.

Listing 5.25. The second test: messages sent to multiple subscribed clients

public class RaceResultsServiceFirstAndSecondTest {

@Test

public void subscribedClientShouldReceiveMessage() { RaceResultsService raceResults = new RaceResultsService(); Client client = mock(Client.class);

Message message = mock(Message.class);

raceResults.addSubscriber(client);

raceResults.send(message);

verify(client).receive(message);

}

@Test

public void messageShouldBeSentToAllSubscribedClients() { RaceResultsService raceResults = new RaceResultsService(); Client clientA = mock(Client.class, "clientA");

Client clientB = mock(Client.class, "clientB");

Message message = mock(Message.class);

raceResults.addSubscriber(clientA);

raceResults.addSubscriber(clientB);

raceResults.send(message);

verify(clientA).receive(message); verify(clientB).receive(message);

}

}

The old test (the one verifying the sending of messages to a single subscriber) is left untouched, even though it seems to be redundant. However, I am going to keep it, so I can always be sure that this functionality will work for a single subscriber.

The second test verifies whether the service works for more than one subscriber.

In order to implement the new test, I need more test doubles of the Client class. Please note the additional String parameter of the mock() method, which will help us to distinguish test doubles when things go wrong.

8Please see the notes on writing Javadocs in Section 4.2.3

82

Chapter 5. Mocks, Stubs, Test Spies

As in the case of the test discussed earlier (see Listing 5.21), both client objects (clientA and clientB) are test spies, and message is a dummy.

This is one of this rare cases when I find the use of "numbered" variable names (clientA, clientB) justified. Usually I try to convey some information by naming all variables meaningfully (e.g. vipClient or clientWithZeroAccount) but this time all I want to say is that these are two different clients. Thus, clientA and clientB sound good to me.

After the test has been run it prints the following error (Listing 5.26).

Listing 5.26. Error - client has not received the message

Wanted but not invoked: clientA.receive(

Mock for Message, hashCode: 11746570

);

-> at com.practicalunittesting.chp05.raceresults.RaceResultsServiceTest

.allSubscribedClientsShouldReceiveMessages(RaceResultsServiceTest.java:39) Actually, there were zero interactions with this mock.

Thanks to the additional String parameter, the failure message precisely tells us that it was clientA that should have been notified.

Well, obviously the addSubscriber() and send() methods of the RaceResultsService class are not able to operate on more than one client. A possible fix is shown below.

Listing 5.27. The second test passed: multiple subscribers receive the message

public class RaceResultsService {

private Collection<Client> clients = new ArrayList<Client>();

public void addSubscriber(Client client) { clients.add(client);

}

public void send(Message message) { for (Client client : clients) {

client.receive(message);

}

}

}

This implementation uses a list of subscribers instead of one subscriber.

The test passes now. The main functionality – that of sending messages to subscribers – works. Good.

Refactoring

The production code looks fine, but the test code really calls out to be refactored. There is an obvious redundancy relating to the creation of the SUT and DOCs in every test method. As discussed previously, we have two options here: leverage the execution model of JUnit (see Section 3.8.3) or introduce a new setUp() method. In this case I have decided to use the first option, as shown below.

83

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