package book.example.threading.executor;
import book.example.common.searching.AuctionDescription;
import book.example.common.searching.AuctionHouse;
import book.example.common.searching.StubAuctionHouse;
import book.example.common.searching.async.AuctionSearchConsumer;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.States;
import org.jmock.integration.junit4.JMock;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.lib.concurrent.Synchroniser;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
@RunWith(JMock.class)
public class AuctionSearch_v1_Tests {
Synchroniser synchroniser = new Synchroniser();
Mockery context = new JUnit4Mockery() {{
setThreadingPolicy(synchroniser);
}};
AuctionSearchConsumer consumer = context.mock(AuctionSearchConsumer.class, "consumer");
StubAuctionHouse auctionHouseA = new StubAuctionHouse("houseA");
StubAuctionHouse auctionHouseB = new StubAuctionHouse("houseB");
AuctionSearch_v1 search = new AuctionSearch_v1(houses(auctionHouseA, auctionHouseB), consumer);
Set<String> keywords = set("sheep", "cheese");
List<AuctionDescription> resultsFromA = asList(auction(auctionHouseA, "1"), auction(auctionHouseA, "2"));
List<AuctionDescription> resultsFromB = asList(auction(auctionHouseB, "1"), auction(auctionHouseB, "2"));
States searching = context.states("activity");
@Test(timeout = 100)
public void searchesAuctionHouses() throws Exception {
auctionHouseA.willReturnSearchResults(keywords, resultsFromA);
auctionHouseB.willReturnSearchResults(keywords, resultsFromB);
context.checking(new Expectations() {{
oneOf(consumer).auctionSearchFound(resultsFromA);
when(searching.isNot("finished"));
oneOf(consumer).auctionSearchFound(resultsFromB);
when(searching.isNot("finished"));
oneOf(consumer).auctionSearchFinished();
then(searching.is("finished"));
}});
search.search(keywords);
waitForSearchToFinish();
}
@Test(timeout = 100)
public void doesNotAnnounceEmptySearchResults() throws Exception {
Set<String> keywords = set("keywords");
auctionHouseA.willReturnSearchResults(keywords, resultsFromA);
auctionHouseB.willReturnSearchResults(keywords, noResults());
context.checking(new Expectations() {{
oneOf(consumer).auctionSearchFound(resultsFromA);
oneOf(consumer).auctionSearchFinished();
then(searching.is("finished"));
}});
search.search(keywords);
waitForSearchToFinish();
}
// more reliable and meaningful than a call to Thread.sleep
private void waitForSearchToFinish() throws InterruptedException {
synchroniser.waitUntil(searching.is("finished"));
}
private List<AuctionDescription> noResults() {
return emptyList();
}
private List<AuctionHouse> houses(AuctionHouse... houses) {
return asList(houses);
}
private AuctionDescription auction(AuctionHouse house, String id) {
return new AuctionDescription(house, id, "test auction " + id);
}
private Set<String> set(String... strings) {
return new HashSet<String>(Arrays.asList(strings));
}
}