This is another example where the last test actually validates that certain messages happen in a particular order. The test is called generatesCorrectSummaryReport and it creates a jMock “Sequence” that verifies the following:
The method SummaryReportPrinter.displayTransactionSummary is called 5 times in a row with the values: 10, 20, 30, 40, 50
Next, the method SummaryReportPrinter.displayTotalSales is called with a value of 150
Finally, the method SummaryReportPrinter.displayBalance is called with a value of 483
The test also allows SummaryReportPrinter.Transaction.getBalance() to be called any number of times
PointOfSaleTerminalTest
package com.objectmentor.post ;
import static org . junit . Assert . assertEquals ;
import junit.framework.JUnit4TestAdapter ;
import org.jmock.Expectations ;
import org.jmock.Mockery ;
import org.jmock.Sequence ;
import org.jmock.integration.junit4.JMock ;
import org.junit.Before ;
import org.junit.Test ;
import org.junit.runner.RunWith ;
@RunWith ( JMock . class )
public class PointOfSaleTerminalTest {
public static junit . framework . Test suite () {
return new JUnit4TestAdapter ( PointOfSaleTerminalTest . class );
}
Mockery context = new Mockery ();
PointOfSaleTerminal pointOfSaleTerminal ;
@Before
public void createPointOfSaleTerminal () {
pointOfSaleTerminal = new PointOfSaleTerminal ();
}
@Test
public void canHaveInitialBalanceSetAndConfirmed () {
pointOfSaleTerminal . setBalance ( 100000 );
assertEquals ( 100000 , pointOfSaleTerminal . getBalance ());
}
@Test
public void balanceReflectsSingleSale () {
final Transaction transacton = context . mock ( Transaction . class );
context . checking ( new Expectations () {
{
one ( transacton ). getAmountDue ();
will ( returnValue ( 15 ));
}
});
pointOfSaleTerminal . setBalance ( 27 );
pointOfSaleTerminal . addTransaction ( transacton );
assertEquals ( 42 , pointOfSaleTerminal . getBalance ());
}
private int calculateAmount ( int index ) {
return index * 10 ;
}
private void addTransaction ( final int index ) {
final Transaction transaction = context . mock ( Transaction . class );
context . checking ( new Expectations () {
{
ignoring ( transaction ). getAmountDue ();
will ( returnValue ( calculateAmount ( index + 1 )));
}
});
pointOfSaleTerminal . addTransaction ( transaction );
}
private void addTransactionSummaryExpectation ( final SummaryReportPrinter summaryReportPrinter ,
final Sequence printSequence , final int index ) {
context . checking ( new Expectations () {
{
one ( summaryReportPrinter ). displayTransactionSummary ( with ( equal ( index )),
with ( equal ( calculateAmount ( index ))));
inSequence ( printSequence );
}
});
}
@Test
public void generatesCorrectSummaryReport () {
final int extectedBalance = 333 ;
pointOfSaleTerminal . setBalance ( extectedBalance );
for ( int i = 0 ; i < 5 ; ++ i ) {
addTransaction ( i );
}
final SummaryReportPrinter summaryReportPrinter = context . mock ( SummaryReportPrinter . class );
final Sequence printSequence = context . sequence ( "printSequence" );
context . checking ( new Expectations () {
{
for ( int i = 1 ; i <= 5 ; ++ i ) {
addTransactionSummaryExpectation ( summaryReportPrinter , printSequence , i );
}
final int expectedTotal = 150 ;
one ( summaryReportPrinter ). displayTotalSales ( with ( equal ( expectedTotal )));
inSequence ( printSequence );
one ( summaryReportPrinter ). displayBalance (
with ( equal ( expectedTotal + extectedBalance )));
inSequence ( printSequence );
}
});
pointOfSaleTerminal . setSummaryReportPrinter ( summaryReportPrinter );
pointOfSaleTerminal . generateSummaryReport ();
}
}
PointOfSaleTerminal
package com.objectmentor.post ;
import java.util.LinkedList ;
import java.util.List ;
public class PointOfSaleTerminal {
List < Transaction > transactions = new LinkedList < Transaction >();
int initialBalance ;
private SummaryReportPrinter summaryReportPrinter ;
public void setBalance ( int balance ) {
this . initialBalance = balance ;
}
public int getBalance () {
int balance = initialBalance ;
for ( Transaction transaction : transactions ) {
balance += transaction . getAmountDue ();
}
return balance ;
}
public void addTransaction ( Transaction transaction ) {
transactions . add ( transaction );
}
public void generateSummaryReport () {
int index = 0 ;
for ( Transaction transaction : transactions ) {
int amountDue = transaction . getAmountDue ();
summaryReportPrinter . displayTransactionSummary (++ index , amountDue );
}
int balance = getBalance ();
int totalSales = balance - initialBalance ;
summaryReportPrinter . displayTotalSales ( totalSales );
summaryReportPrinter . displayBalance ( balance );
}
public void setSummaryReportPrinter ( SummaryReportPrinter summaryReportPrinter ) {
this . summaryReportPrinter = summaryReportPrinter ;
}
}
SummaryReportPrinter
package com.objectmentor.post ;
public interface SummaryReportPrinter {
void displayTransactionSummary ( int index , int totalAmount );
void displayTotalSales ( int totalAmount );
void displayBalance ( int amount );
}
Transaction
package com.objectmentor.post ;
public interface Transaction {
int getAmountDue ();
}
Comments