July 23, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Working With Design Patterns: Chain of Responsibility

  • May 7, 2008
  • By Jeff Langr
  • Send Email »
  • More Articles »

Listing 4: JUnit tests.

import static org.junit.Assert.*;

import org.junit.*;

public class ChainTest {
   private Manager manager;
   private VicePresident vp;
   private CEO ceo;
   private ExpenseReport report;

   private static final int SMALL_AMOUNT = 100;
   private static final int VP_AMOUNT = 7000;
   private static final int CEO_AMOUNT = 207000;

   @Before
   public void amountPreconditions() {
      assertTrue(SMALL_AMOUNT <= manager.getDollarLimit());
      assertTrue(manager.getDollarLimit() < VP_AMOUNT &&
            VP_AMOUNT <= vp.getDollarLimit());
      assertTrue(vp.getDollarLimit() < CEO_AMOUNT);
   }

   @Before
   public void createReport() {
      report = new ExpenseReport();
   }

   @Before
   public void createDefaultChain() {
      manager = new Manager("Joe", false);
      vp = new VicePresident("Jane");
      ceo = new CEO("Zeus");

      manager.setNextApprover(vp);
      vp.setNextApprover(ceo);
   }

   @Test
   public void approvedByManager() {
      report.setTotalDollarAmount(SMALL_AMOUNT);
      manager.handle(report);
      assertApprovedBy(manager);
   }

   @Test
   public void approvedByVPWhenOverManagerLimit() {
      report.setTotalDollarAmount(VP_AMOUNT);
      manager.handle(report);
      assertApprovedBy(vp);
   }

   @Test
   public void approvedByCEOWhenOverVPLimit() {
      report.setTotalDollarAmount(CEO_AMOUNT);
      manager.handle(report);
      assertApprovedBy(ceo);
   }

   @Test
   public void approvedIntlByIntlManager() {
      report.setTotalDollarAmount(SMALL_AMOUNT);
      report.setIsInternationalTravel(true);
      manager.setCanApproveInternational(true);
      manager.handle(report);
      assertApprovedBy(manager);
   }

   @Test
   public void approvedIntlByVPWhenManagerNotIntl() {
      report.setTotalDollarAmount(SMALL_AMOUNT);
      report.setIsInternationalTravel(true);
      assertFalse(manager.canApproveInternational());
      manager.handle(report);
      assertApprovedBy(vp);
   }

   @Test
   public void approvedByVPWhenManagerOutOfOffice() {
      report.setTotalDollarAmount(SMALL_AMOUNT);
      manager.setOutOfOffice(true);
      manager.handle(report);
      assertApprovedBy(vp);
   }

   @Test
   public void rejectedWhenCEOOutOfOffice() {
      report.setTotalDollarAmount(CEO_AMOUNT);
      ceo.setOutOfOffice(true);
      manager.handle(report);
      assertSame(State.rejected, report.state());
   }

   @Test
   public void approvedByPeerWhenManagerOutOfOffice() {
      report.setTotalDollarAmount(SMALL_AMOUNT);
      Manager peer = new Manager("Jim", false);
      peer.setNextApprover(vp);
      manager.setOutOfOffice(true);
      manager.setNextApprover(peer);

      manager.handle(report);
      assertApprovedBy(peer);
   }


   private void assertApprovedBy(Approver approver) {
      assertSame(State.approved, report.state());
      assertSame(approver, report.getHandler());
   }
}

The client working with the chain of responsibility doesn't know and doesn't really care which approver will finally handle the expense report. In this implementation, the employee submitting the report knows the initial approver—his or her manager. However, there's no reason that the client even needs to know this much information. A factory could produce an appropriate Approver implementation for the client.

Figure 1: Chain of Responsibility.

About the Author

Jeff Langr is a veteran software developer with over a quarter century of professional software development experience. He's written two books, including Agile Java: Crafting Code With Test-Driven Development (Prentice Hall) in 2005. Jeff has contributed a couple chapters to Uncle Bob Martin's upcoming book, Clean Code. Jeff has written over 75 articles on software development, with over thirty appearing at Developer.com. You can find out more about Jeff at his site, http://langrsoft.com, or you can contact him via email at jeff at langrsoft dot com.





Page 3 of 3



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel