SlideShare a Scribd company logo
Testing Rich Domain Models


           Chris i h d
           Ch i Richardson

      Author of POJOs in Action
   Chris Richardson C
   Ch i Ri h d      Consulting, I
                          lti   Inc
http://www.chrisrichardson.net
3/1/2009                                                                  1
              Copyright (c) 2007 Chris Richardson. All rights reserved.
Overview



           Testing a rich
                 g
           domain model:
            Why? How?

3/1/2009                                                                  2
              Copyright (c) 2007 Chris Richardson. All rights reserved.
About Chris

                                                     Grew up in England
                                                     Live in Oakland, CA
                                                     Over twenty years of software
                                                     development experience
                                                               Building object-oriented
                                                                      g   j
                                                               software since 1986
                                                               Using Java since 1996
                                                               Using J2EE since 1999
                                                     Author of POJOs in Action
                                                     Speaker at JavaOne, JavaPolis,
                                                     SpringOne, NFJS, JUGs, ….
                                                     Chair of the eBIG Java SIG in
                                                     Oakland (www.ebig.org)
                                                     Run a consulting and training
                                                     company that helps organizations
                                                     build better software faster




3/1/2009                                                                                  3
           Copyright (c) 2007 Chris Richardson. All rights reserved.
Agenda
 g
    Introduction
    Testing services
    Testing entities and value objects
          g                       j
    Taming test fixture logic
    Simplifying verification code
    Writing more meaningful tests




3/1/2009                                                                   4
               Copyright (c) 2007 Chris Richardson. All rights reserved.
Using the Domain Model Pattern
    g
    Traditional enterprise Java applications:
           Business l i i f t service
           Bi       logic in fat  i
           Services manipulate dumb Java beans
           Doesn t
           Doesn't handle complexity
    Domain model pattern:
           Business logic spread amongst a collection
           of classes
            fl
           Many classes are true objects having both
           state (fields) and behavior (
                 (      )              (methods) the
                                               )
           state
    Many classes correspond to real world
    concepts: Order Customer, …
              Order, Customer
3/1/2009                                                                          5
                      Copyright (c) 2007 Chris Richardson. All rights reserved.
Procedural versus OO
                Presentation Tier
                                                                                                Presentation Tier


Business Tier

                                                                       Business Tier
Transaction
  Scripts
                                                                         Facade
 (Session
  Beans)
                                                                         Domain Model




     Data
    Objects
    Obj




                                                                                                Data Access Tier
                Data Access Tier




   3/1/2009                                                                                                         6
                                    Copyright (c) 2007 Chris Richardson. All rights reserved.
An example domain model
       p
                                                    Web Tier

                                Behavior
       Business Tier


                                             MoneyTransferService


                                BankingTransaction transfer(fromId, toId, amount)




                                                           from
                                                                         Account
                                          Banking                                                       Account
           BankingTransaction
                                        Transaction                                                    Repository
               Repository
                                                                     balance
                                                            to
                                      amount                                                          findAccount(id)
           addTransaction(…)                                         debit(amount)
                                      date
                                                                     credit(amount)




                                                                                                          Explicit
                                                                   <<interface>>
                                                                   OverdraftPolicy
                                                                                                       Representation
                           State +
                                                                                                           of key
                           Behavior                                                    Limited
                                                                                                         concepts
                                                                                                                p
                                                             NoOverdraft              Overdraft
                                                               Policy
                                                                    y
                                                                                    limit




3/1/2009                                                                                                                7
                                          Copyright (c) 2007 Chris Richardson. All rights reserved.
Why test?
  y
    Write new code more easily
           Automates what we are doing already
           - Right!?
           Run fast unit tests instead of slower
           web application
                 pp
           Use TDD to incrementally solve a
           problem
    Tests are a safety net
                     y
           Confidently change existing code
           Easier to refactor code to prevent
           decay
           The application has longer, healthier
           life
    Fewer bugs that impact customers
            g         p
    AND development
3/1/2009                                                                           8
                       Copyright (c) 2007 Chris Richardson. All rights reserved.
Why test a domain model?
  y

    Benefits of pushing tests down
                p     g
    the hierarchy:
           Easier and cheaper
           Faster
           Better error localization
    You change a complex interest
    calculation:
    How do you want to test it:
           Through a changing GUI?
           With simple unit tests
    When do you want to find out
    whether it works?
           15 minutes later after running
           web tests?
           10 seconds later after running
           hundreds of unit tests?
    Determining why a test fails?
           Because of a problem with the
           database or UI?
           Because the algorithm was
           wrong?




3/1/2009                                                                                    9
                                Copyright (c) 2007 Chris Richardson. All rights reserved.
Domain models make testing easier
                         g
    More modular:
           Smaller classes/methods that are easier
           to test
    Business l i i
       i     logic implemented b
                      l      d by
    immutable value objects
           Functions are easier to test that code
                                         h     d
           with side-effects
    Back to basics - POJOs with no
    dependencies on infrastructure
           Quickly test in isolation
3/1/2009                                                                          10
                      Copyright (c) 2007 Chris Richardson. All rights reserved.
Domain models make testing more
difficult…
    Domain models are often used when the
    business logic is complex
    Objects are structurally more complex
           Not relational – i.e. not flat, coarse-grained
           Finer grained objects, i.e. many classes map to the
           same table)
           Richer relationships between objects
           Deeper object graphs
    Object behavior is more complex
           Behavior determined by collaborators + internal
           state (reflects previous method invocations)
           Classes are often modal: imposes ordering on
           method invocations

3/1/2009                                                                           11
                       Copyright (c) 2007 Chris Richardson. All rights reserved.
…Domain models make testing
more difficult
    Richer collaborations
           Service does more than invoke getters and
           setters on domain objects
           Domain objects invoke methods on one
           another
    Encapsulation
        p
           Domain Objects != JavaBeans
           Perhaps getters but preferably not setters
           Initializing objects is more complex
           Verifying object state might be more difficult


3/1/2009                                                                          12
                      Copyright (c) 2007 Chris Richardson. All rights reserved.
Excellent testing book
                g
     Test smells and how to fix them
           Obscure test
           Fragile test
           Test code duplication
           …
     Comprehensive pattern
     C      h  i     tt
     language:
           Four phase test
           Minimal fixture
           Test utility method
           Test helper
           Humble Object
           …




3/1/2009                                                                            13
                        Copyright (c) 2007 Chris Richardson. All rights reserved.
Agenda
 g
    Introduction
    Testing services
    Testing entities and value objects
          g                       j
    Taming test fixture logic
    Simplifying verification code
    Writing more meaningful tests




3/1/2009                                                                   14
               Copyright (c) 2007 Chris Richardson. All rights reserved.
What's a Service?

    A role that some domain                             public interface MoneyTransferService {

    model classes play                                       BankingTransaction transfer(String fromAccountId,
                                                                  String toAccountId, double amount)
    Implements logic that                                         throws MoneyTransferException;

    cannot be put in a single                           }
    entity
    Not
    N t persistent
             it t                                       public class MoneyTransferServiceImpl implements MoneyTransferService
                                                        {
    Consists of an interface
    and an implementation                                   private final AccountRepository accountRepository;

    class                                                   private final BankingTransactionRepository
                                                                       bankingTransactionRepository;
    Service method usually:
           Invoked (indirectly) by                          public MoneyTransferServiceImpl(AccountRepository accountRepository,
                                                               BankingTransactionRepository bankingTransactionRepository) {
           presentation tier                                  this.accountRepository = accountRepository;
           Invokes one or more                                this.bankingTransactionRepository = bankingTransactionRepository;
           repositories                                     }

           Invokes one or more entities                     public B ki T
                                                               bli BankingTransaction t
                                                                                   ti  transfer(String f
                                                                                            f (St i    fromAccountId,
                                                                                                           A     tId

    Well-designed services                                      String toAccountId, double amount) {
                                                              …
    are thin                                                  fromAccount.debit(amount);
                                                              toAccount.credit(amount);
           Improves code quality                              …
           Makes them easier to test                        }

                                                        }




3/1/2009                                                                                                                15
                            Copyright (c) 2007 Chris Richardson. All rights reserved.
How to test a service?

p
public class MoneyTransferServiceImpl implements MoneyTransferService {
                 y                 p    p            y

    private final AccountRepository accountRepository;
    private final BankingTransactionRepository bankingTransactionRepository;

    public MoneyTransferServiceImpl(AccountRepository accountRepository,
        BankingTransactionRepository b ki
           ki          i       i     bankingTransactionRepository) {
                                                    i       i    )
      this.accountRepository = accountRepository;
      this.bankingTransactionRepository = bankingTransactionRepository;
    }

    public BankingTransaction transfer(String fromAccountId
                                              fromAccountId,
        String toAccountId, double amount) throws MoneyTransferException {
      Account fromAccount = accountRepository.findAccount(fromAccountId);
      Account toAccount = accountRepository.findAccount(toAccountId);
      fromAccount.debit(amount);
      toAccount.credit(amount);
      TransferTransaction txn = new TransferTransaction(fromAccount,
          toAccount, amount, new Date());
      bankingTransactionRepository.addTransaction(txn);
      return txn;
                                                                                         Database access
}

…


3/1/2009                                                                                                   16
                             Copyright (c) 2007 Chris Richardson. All rights reserved.
Writing service integration tests

    Fixture logic:                               public class SpringMoneyTransferServiceTests extends
                                                    AbstractDependencyInjectionSpringContextTests {
                                                  …
           Creates service                        @Override
                                                  protected String[] getConfigLocations() {
                                                    return new String[] { quot;classpath:/appCtx/*.xmlquot; };
           Initializes database                   }


    Exercise phase:
    E    i    h                                  public void setService(MoneyTransferService service) {
                                                     bli   id tS     i (M    T    fS     i       i)
                                                    this.service = service;
                                                  }
           Calls service                         @Override

    Verification:
                                                 protected void onSetUp() throws Exception {
                                                   super.onSetUp();
                                                   fromAccount = AccountMother

           Check state of                             .makeAccountWithNoOverdraft(FROM_ACCOUNT_INITIAL_BALANCE);
                                                   toAccount = AccountMother

           database and                               .makeAccountWithNoOverdraft(TO_ACCOUNT_INITIAL_BALANCE);
                                                   fromAccountId = fromAccount.getAccountId();

           return values                           toAccountId = toAccount.getAccountId();
                                                   repository.addAccount(fromAccount);
                                                   repository.addAccount(toAccount);
                                                   repository addAccount(toAccount);

    Teardown:                                    }

                                                 public void testTransfer() {
           clean up                                 service.transfer(fromAccountId, toAccountId, 5);
                                                    assertBalance(FROM_ACCOUNT_INITIAL_BALANCE - 5, fromAccountId);
           (somehow)                                assertBalance(TO_ACCOUNT_INITIAL_BALANCE + 5, toAccountId);
                                                  }




3/1/2009                                                                                                     17
                           Copyright (c) 2007 Chris Richardson. All rights reserved.
The trouble with integration tests
                     g
    Require lots of setup
           Setting up the database
                  gp
           Initializing the database
           …
    10x-100x slower than in-memory tests:
                                 y
           Use an in-memory database, e.g. HSQLDB
           Don’t commit transactions
    Database = persistence ⇒ test interference
               p
           Execute each test in a transaction that is rolled back
           ⇒ can interfere with session flushing/object loading
           Recreate the database schema ⇒ works well with
           HSQLDB
           Somehow write tests that only see data that they
           insert – can be tricky
    We still need integration tests but we can often
                      g
    do better…
3/1/2009                                                                             18
                         Copyright (c) 2007 Chris Richardson. All rights reserved.
Faster testing with mock objects
             g             j

                                                     A mock object
                                                     simulates the real
                                                     object:
                                                               Returns values or
                                                               throws exceptions
                                                               th             ti
                                                               Verifies that the
                                                               expected methods are
                                                               called
                                                     Using mocks:
                                                               Simplifies tests
                                                               Speeds up tests
                                                               Enables an obje t to
                                                                           object
                                                               be tested in isolation
                                                               Enables top-down
                                                               development


3/1/2009                                                                                19
           Copyright (c) 2007 Chris Richardson. All rights reserved.
Creating mocks
       g
    Write your own mocks
           Simple for interfaces but it becomes
           tedious.
           How t mock concrete classes?
           H    to     k        tl        ?
    Use a mock object framework
           jMOCK, EasyMock
    Create and configure mock object
           Specify expected method and arguments
           Define method behavior: return value or
           throw exception
           th          ti
3/1/2009                                                                         20
                     Copyright (c) 2007 Chris Richardson. All rights reserved.
Mock objects example: p
            j         p    part 1
import org.jmock…;

public class MoneyTransferServiceTests extends MockObjectTestCase {

    protected void setUp() {
      super.setUp();
      accountRepository = mock(AccountRepository class);
                          mock(AccountRepository.class);
      bankingTransactionRepository =
                          mock(BankingTransactionRepository.class);
      service = new MoneyTransferServiceImpl(accountRepository,
          bankingTransactionRepository);
                                                                                      Create
                                                                                      service with
      fromAccount = AccountMother.makeAccount(100);
                                                                                      mock
      toAccount = AccountMother.makeAccount(200);
      fromAccountId = fromAccount getAccountId();
                      fromAccount.getAccountId();
                                                                                      repositories
                                                                                            ii
      toAccountId = toAccount.getAccountId();
}




     3/1/2009                                                                                        21
                          Copyright (c) 2007 Chris Richardson. All rights reserved.
Mock objects example: p
       j         p    part 2

p
public class MoneyTransferServiceTests extends TestCase {
                 y

 public void testTransfer_normal() throws Exception {
    checking(new Expectations() {
      {
        one(accountRepository).findAccount(fromAccountId);
                  will(returnValue(fromAccount));
                   ill(        l (f           ))
        one(accountRepository).findAccount(toAccountId);
                  will(returnValue(toAccount));
        one(bankingTransactionRepository).addTransaction(
                                            with(is(BankingTransaction.class)));
      }
    });

      BankingTransaction result = service
          .transfer(fromAccountId, toAccountId, 30);

      assertNotNull(result);

      MoneyUtil.assertMoneyEquals(70.0, fromAccount.getBalance());
      MoneyUtil.assertMoneyEquals(230.0, toAccount.getBalance());

  }



3/1/2009                                                                                   22
                               Copyright (c) 2007 Chris Richardson. All rights reserved.
Downsides of mocks
    Testing the collaboration of objects =
    white box testing
    Tests can be brittle
           Change design without changing what it
           does ⇒ failing tests
           Discourages ddevelopers f
                             l     from writing
           tests
    Fortunately,
    Fortunately many collaborations are
    stable
           e.g.
           e g between services and repositories
3/1/2009                                                                        23
                    Copyright (c) 2007 Chris Richardson. All rights reserved.
Mock selectively!
               y
    Collaborators that slow tests down or
    introduce undesirable coupling:
           Repositories
           Remote Services
    Collaborators that require elaborate
    initialization,
           Stateful entities and value objects
    Collaborators that don't exist (yet)
           Entities when developing top down
                                    top-down
    Applications where message ordering is
    important

3/1/2009                                                                          24
                      Copyright (c) 2007 Chris Richardson. All rights reserved.
Agenda
 g
    Introduction
    Testing services
    Testing entities and value objects
           g                      j
    Taming test fixture logic
    Simplifying verification code
    Writing more meaningful tests




3/1/2009                                                                  25
              Copyright (c) 2007 Chris Richardson. All rights reserved.
What's an Entity?
               y

   Objects with a                           public class Account {


   distinct identity                         private int id;


   Typically correspond
                                             private double balance;



   to real world
                                             private OverdraftPolicy overdraftPolicy;

                                             private String accountId;
   concepts                                  private CalendarDate dateOpened;

   Almost always                             Account() {

   persistent
                                             }

                                             public void debit(double amount) throws MoneyTransferException {

   Encapsulate state and                       assert amount > 0;
                                               double originalBalance = balance;

   behavior                                    double newBalance = balance - amount;
                                               overdraftPolicy.beforeDebitCheck(this, originalBalance, newBalance);
                                               balance = newBalance;

   Often modal ⇒                               overdraftPolicy.afterDebitAction(this, originalBalance, newBalance);
                                             }

   testing is more                           public void credit(double amount) {

   difficult                                   assert amount > 0;
                                               balance += amount;
                                             }




3/1/2009                                                                                                   26
                 Copyright (c) 2007 Chris Richardson. All rights reserved.
What's a Value Object?
                 j
                                                                                       public class Account

 Objects that are defined
                                                                                         private CalendarDate dateOpened;
                                                public class CalendarDate {

 by the values of their                                                                 …
                                                    p ate ate
                                                    private Date date;                 }
 attributes                                         CalendarDate() {

 Two instances with
                                                    }


 identical values can be                            public CalendarDate(Date date) {
                                                      this.date = date;
 used interchangeably                               }


 Two flavors                                        public Date getDate() {
                                                      return date;
      Persistent – parts of                         }

      entities                                      public double getYearsOpen() {
                                                     Calendar then = Calendar.getInstance();
      Transient – intermediate                       then.setTime(date);
      values                                         Calendar now = Calendar.getInstance();


 Ideally immutable                                      int yearsOpened = now.get(Calendar.YEAR) –
                                                                          then.get(Calendar.YEAR);

 Often missing from                                     int monthsOpened = now.get(Calendar.MONTH) -
                                                                         then.get(Calendar.MONTH);
 procedural code
       d   ld                                           if (monthsOpened < 0) {
                                                           (   th O     d
                                                          yearsOpened--;

 Have encapsulated state                                  monthsOpened += 12;
                                                        }
 and behavior                                           return yearsOpened + (monthsOpened/12.0);

                                                    }

                                                }




3/1/2009                                                                                                       27
                     Copyright (c) 2007 Chris Richardson. All rights reserved.
Aggregates
 gg g

                                                     A cluster of related
                                                     entities and values
                                                     Behaves as a unit
                                                     Has a root
                                                     Has b
                                                     H a boundaryd
                                                     Objects outside the
                                                     aggregate can only
                                                     reference the root
                                                     Deleting the root
                                                     removes everything

                                                     Tests often create
                                                     and test aggregates
                                                     rather than
                                                     individual objects


3/1/2009                                                                    28
           Copyright (c) 2007 Chris Richardson. All rights reserved.
Tests for entities and value objects
                               j
    Fixture logic
           Create object under test (OUT) (often an
           aggregate)
           Create collaborators (also aggregates)
    Execution
    E ec tion
           Invoke method on OUT
    Verification
           Return value
           State of OUT
           State of collaborators
    Cleanup
           Usually do nothing – just use the g
                  y         gj               garbage
                                                  g
           collector
3/1/2009                                                                          29
                      Copyright (c) 2007 Chris Richardson. All rights reserved.
Testing a POJO domain object
      g                 j

                                                       p
                                                       public class AccountTests extends TestCase {
p
public class Account {
                                                           private Account account;
private String accountId;
private double balance;                                    public void setUp() {
private OverdraftPolicy                                       account = new Account(quot;ABCquot;, 10.0, new
        overdraftPolicy;
            d ftP li                                                             NoOverdraftAllowed());
                                                                                       d f ll     d())
                                                            }
public double getBalance() {
                                                           public void testInitialBalance() {
  return balance;
                                                              MoneyUtil.assertMoneyEquals(10.0,
}                                                                              account.getBalance());
                                                                               account getBalance());
                                                           }
public void debit(double amount)
                                                           public void testDebit() {
{…}
                                                             account.debit(6);
                                                             MoneyUtil.assertMoneyEquals(4.0,
public void credit(double
                                                                             account.getBalance());
       amount) { … }                                       }
                                                       …
Relatively easy to write tests                         }

that run blindingly fast


3/1/2009                                                                                        30
                         Copyright (c) 2007 Chris Richardson. All rights reserved.
Mocking collaborators
      g
    Used less often - collaborators are
    usually fast to create
    But it can sometimes simplify tests
    Account and OverdraftPolicy
           Separate tests Account and
           OverdraftPolicies ⇒ Fewer, simpler tests
           But perhaps causes a feeling that you
           are not testing completely
                 t t ti         ltl
    Useful when creating a collaborator
    requires writing a l t of code
        i      iti     lot f d
3/1/2009                                                                         31
                     Copyright (c) 2007 Chris Richardson. All rights reserved.
Agenda
 g
    Introduction
    Testing services
    Testing entities and value objects
          g                       j
    Taming test fixture logic
    Simplifying verification code
    Writing more meaningful tests




3/1/2009                                                                   32
               Copyright (c) 2007 Chris Richardson. All rights reserved.
What's a fixture
    Fixture = everything that needs to
    be in place to test an object
           Object we want to test
           Its collaborators
    Fixture is created by test fixture
    logic:
           Code in the test methods themselves
           Junit 3.x setUp()
           JUnit 4/TestNG @Before* annotations


3/1/2009                                                                         33
                     Copyright (c) 2007 Chris Richardson. All rights reserved.
The challenge of test fixtures
           g
    Creating objects isn't always easy
           Individual objects have lots of parameters
           Objects are often belong to aggregates
    Test fixtures often create multiple
    T t fi t       ft       t    lti l
    objects
           MoneyTransferServiceTests needs two
           accounts
    Multiple tests need the same set of
    objects
             AccountTests, MoneyTransferServiceTests need
             similar A
              i il Account objects
                           t bj t

3/1/2009                                                                          34
                      Copyright (c) 2007 Chris Richardson. All rights reserved.
Object g p
  j    graphs can be complicated
                        p
                                                                       We need all
                                                                       of these
                                                                       objects to
                                                                       test a
                                                                       Project!




3/1/2009                                                                             35
           Copyright (c) 2007 Chris Richardson. All rights reserved.
Constructing individual objects can
be tricky
        y
    Best way to construct an object is to
    use a constructor:
           Supports objects without setters
           Supports immutable objects
           Forces you to support everything that's
           required
    Limitations of constructors:
           Lots of constructor arguments ⇒ code is
           difficult
           diffi l to read
                         d
           Optional arguments ⇒ multiple
           constructors

3/1/2009                                                                         36
                     Copyright (c) 2007 Chris Richardson. All rights reserved.
The alternative to constructors

Project project = new Project(initialStatus);
    project.setName(quot;Test Project #1quot;);
    project.setDescription(quot;descriptionquot;);
    project.setRequirementsContactName(quot;Rick Jonesquot;);
    project.setRequirementsContactEmail(quot;jones@nowhere.comquot;);
    project.setType(ProjectType.EXTERNAL_DB);
    project.setArtifacts(new ArtifactType[] {
        ArtifactType.ARCHITECTURE,
        ArtifactType.DEPLOYMENT, ArtifactType.MAINTENANCE });
    project.setInitiatedBy(user);




      •Handles optional parameters
      •Is more readable
      •But lots of noise: 'project set'
                           project.set


3/1/2009                                                                            37
                        Copyright (c) 2007 Chris Richardson. All rights reserved.
Constructing objects fluently
           g   j            y

Project project = new Project(initialStatus)
        .name(quot;Test Project #1quot;)
        .description(quot;Excellent projectquot;)
        .initiatedBy(user)
        .requirementsContactName(quot;Rick Jonesquot;)
        .requirementsContactEmail(quot;jones@nowhere.comquot;)
        .type(ProjectType.EXTERNAL_DB)
        .artifact(ArtifactType.ARCHITECTURE)
        .artifact(ArtifactType.DEPLOYMENT)
        .artifact(ArtifactType.MAINTENANCE);

           • Chained method calls




3/1/2009                                                                             38
                         Copyright (c) 2007 Chris Richardson. All rights reserved.
Pros and cons of this approach
                       pp
    Benefits:
           Less noise
           Meaning of each value is clear
    Drawbacks:
           Breaks encapsulation – objects must
           have mutators/setters
           Doesn't work with immutable objects




3/1/2009                                                                         39
                     Copyright (c) 2007 Chris Richardson. All rights reserved.
Fluently creating immutable objects
       y        g             j
    See
    http://developers.sun.com/learning/javaoneonl
    http://developers sun com/learning/javaoneonl
    ine/2007/pdf/TS-2689.pdf
 Project project = new Project.ProjectBuilder(initialStatus)
        .name(quot;Test Project #1quot;)
             (quot;        j
        .description(quot;descriptionquot;)
        .initiatedBy(user)
        .requirementsContactName(quot;Rick Jonesquot;)
        .requirementsContactEmail(quot;jones@nowhere.comquot;)
             i       C         il(quot;j    @    h      quot;)
        .type(ProjectType.EXTERNAL_DB)
        .artifact(ArtifactType.ARCHITECTURE)
        .artifact(ArtifactType.DEPLOYMENT)
        .artifact(ArtifactType.MAINTENANCE)
           tif t(A tif tT      MAINTENANCE)
        .make();
                             • Initialize the mutable builder
                             • make() instantiates the domain
                             object i
                             obje t via a constructor
                                             on t  to
                             • Allows entity to be immutable
3/1/2009                                                                         40
                     Copyright (c) 2007 Chris Richardson. All rights reserved.
Nested Entity Builder example
            y             p
class Project {

  public class ProjectBuilder {
    private String name;
    …

      public ProjectBuilder(Status initialStatus) {
        this.status = status;
      }

      ProjectBuilder name(String name) {
        this.name = name;
        return this;
      }

      public Project make() {
        // Verify that we have everything
        return new Project(this);
      }
  }
                                                              • Pass builder as the sole
  public Project(ProjectBuilder builder) {
                                                              constructor argument
    this.name = builder.name;
    this.initiatedBy = builder.initiatedBy;
  }



3/1/2009                                                                                   41
                              Copyright (c) 2007 Chris Richardson. All rights reserved.
Centralizing object creation with
Object Mothers
  j
     Fluent interfaces can help
     but                                                              public class ProjectMother {

           Fixture logic can still be                                     public static Project
           complex                                                             makeProjectInProposalState (
                                                                                    Status initialStatus, User user) {
           Same object created in                                           …
           multiple t t ⇒ d li ti
              lti l tests    duplication                                  }
     Eliminate duplication:                                               public static Project
           Centralize object creation in                                     makeProjectInRequirementsState(
                                                                                    Status initialStatus, User user) {
           a test utility class called an
           Object Mother                                                      …
           Defines factory methods for                                    }
           creating fully formed
           aggregate                                                  }
           Different methods for
           different aggregate states
See: http://www xpuniverse com/2001/pdfs/Testing03 pdf
     http://www.xpuniverse.com/2001/pdfs/Testing03.pdf


3/1/2009                                                                                                       42
                         Copyright (c) 2007 Chris Richardson. All rights reserved.
Creating multiple connected
aggregates
 gg g

    Each Object Mother
    method creates a
    single aggregate
    But
    B t some tests need
               tt        d
    to create multiple
    aggregates with
    shared sub-
     h    d   b
    aggregates                               itDepartment = DepartmentMother.makeItDepartment();

    Must avoid                               itProjectManager =

    duplicating that code
                                                    UserMother.makeProjectManager(itDepartment);
                                              itBusinessAnalyst =
                                                     UserMother.makeBusinessAnalyst(itDepartment);
    in multiple fixtures                     projectInCompleteState =
                                                    ProjectMother.makeProjectInCompleteState(…);
                                             projectInRequirementsState =
                                                 ProjectMother.makeProjectInRequirementsState(…);
                                                 P j tM th        k P j tI R     i     t St t ( )
                                             …



3/1/2009                                                                                         43
                  Copyright (c) 2007 Chris Richardson. All rights reserved.
Use stateful object mothers
               j
    Test instantiates object mother
    Object mother's constructor
           Creates aggregates (by calling their
           Object Mothers)
           Stores them in (public) fields
    Test gets the data it needs from the
    object mother




3/1/2009                                                                         44
                     Copyright (c) 2007 Chris Richardson. All rights reserved.
Example of a stateful mother
                                                                public class ProjectTests extends TestCase {


                                                                  private Project project;
                                                                  private User projectManager;
                                                                  private User businessAnalyst;
public class PTrackWorld {
                                                                  protected void setUp() throws Exception {
    private final Department itDepartment;                          PTrackWorld world = new PTrackWorld();
    private fi l User itP j tM
      i t final U      itProjectManager;                            projectManager = world.getItProjectManager();
    private final Project projectInCompleteState;                   businessAnalyst = world.getItBusinessAnalyst();
                                                                    project = world.getProjectInProposalState();
                                                                  }
    …

    public PTrackWorld() {
     itDepartment = DepartmentMother.makeItDepartment()'

        itProjectManager = UserMother.makeProjectManager(itDepartment);
        stateMachine = DefaultStateMachineFactory.makeStateMachine(quot;defaultquot;);
        initialStatus = stateMachine.getInitialStatus();
        projectInCompleteState = ProjectMother.makeProjectInCompleteState(initialStatus,
                                            itProjectManager, getAllITDepartmentEmployees());
        …
    }

}



        3/1/2009                                                                                                      45
                                         Copyright (c) 2007 Chris Richardson. All rights reserved.
Object Mother design
  j               g
    Choices
           Same data each time vs. random data
           Referenced aggregates as parameters vs. create
           those aggregates too
    Tip: use descriptive names
           Bad: makeProject1(), makeProject2(), ...
           Better: makeProjectIn<State>(), …
    Tip: use Object Mothers from day 1
    But don’t create obscure tests
           Hiding details in mothers can make tests difficult to
           understand
           ShoppingCartMother.makeWithInstockPartBackorderedPartandDiscontinuedPart() ?!?

           Need to find the balance between too much and too
           little



3/1/2009                                                                                   46
                               Copyright (c) 2007 Chris Richardson. All rights reserved.
Agenda
 g
    Introduction
    Testing services
    Testing entities and value objects
          g                      j
    Taming test fixture logic
    Simplifying verification code
    Writing more meaningful tests




3/1/2009                                                                   47
               Copyright (c) 2007 Chris Richardson. All rights reserved.
Writing readable verification logic
    Verification phase verifies that expected
    outcome has been obtained
    State verification makes assertions about:
           Returned value
           State of object under test
           State of collaborators
    Test frameworks provide the basic assert
    methods but we must:
           Ensure readability
           Avoid code duplication

3/1/2009                                                                           48
                       Copyright (c) 2007 Chris Richardson. All rights reserved.
Using Custom Assertions

    Verifying the state of object
           multiple assert…() calls = obscure code
           In multiple tests = code duplication
    Verification code calls a Test Utility
    Method that makes assertions
    Has an Intention Revealing Name
    Benefits:
           Makes the code more readable
           Eliminates duplication
                        p

3/1/2009                                                                         49
                     Copyright (c) 2007 Chris Richardson. All rights reserved.
Example – before and after
protected void setUp() throws Exception {
  PTrackWorld world = new PTrackWorld();
  projectManager = world.getItProjectManager();

    project = world.getProjectInProposalState();
                                                                                                  protected void setUp() throws Exception {
    startTime = new Date();
                                                                                                  …
                                                                                                     expectedOperation0 =
    state0 = world.getInitialState();
                                                                                                       new Operation(null, projectManager,
    state1 = state0.getApprovalStatus();
                                                                                                                     state0, state1,
    state2 = state1.getApprovalStatus();
                    g   pp            ();
                                                                                                                     quot;Excellentquot;);
                                                                                                                     quot;     ll   quot;)
}
                                                                                                   }
public void testChangeStatus() throws InterruptedException {
                                                                                                   public void testChangeStatus()
  boolean result = project.changeStatus(true,
                                                                                                  {
                              projectManager, quot;Excellentquot;);
                                                                                                     boolean result = project.changeStatus(true,
  Date endTime = new Date();
                                                                                                                    projectManager, quot;E
                                                                                                                       j tM         quot;Excellentquot;);
                                                                                                                                         ll tquot;)
                                                                                                     Date endTime = new Date();
    assertTrue(result);
    assertEquals(state1, project.getStatus());
                                                                                                        assertTrue(result);
    assertEquals(1, project.getHistory().size());
                                                                                                        assertEquals(state1, project.getStatus());
    Operation operation = project.getHistory().get(0);
                                                                                                        assertHistoryContains(project,
                                                                                                        assertHistoryContains(project
    assertEquals(quot;Excellentquot;, operation.getComments());
               l (quot;      ll  quot;         i        C      ())
                                                                                                               startTime, endTime,
    assertEquals(projectManager, operation.getUser());
                                                                                                               expectedOperation0);
    assertEquals(state0, operation.getFromStatus());
                                                                                                    }
    assertEquals(state1, operation.getToStatus());
    assertFalse(operation.getTimestamp().before(startTime));
    assertFalse(operation.getTimestamp().after(endTime));
}




      3/1/2009                                                                                                                             50
                                              Copyright (c) 2007 Chris Richardson. All rights reserved.
Example - After
 private void assertHistoryContains(Project project, Date startTime,
                                     Date endTime,
                                     Operation... expectedOperations) {
    int i = 0;
    List<Operation> history = project.getHistory();
    assertEquals(expectedOperations.length, history.size());
    for (Operation expectedOperation : expectedOperations) {
      Operation operation = history.get(i++);
      assertOperationEqual(expectedOperation, startTime, endTime,
      assertOperationEqual(expectedOperation startTime endTime
                            operation);
      startTime = operation.getTimestamp();
    }
  }



           private void assertOperationEqual(Operation expectedOperation, Date startTime,
                                              Date endTime, Operation operation) {
              assertEquals(expectedOperation.getComments(), operation.getComments());
              assertEquals(expectedOperation.getUser(), operation.getUser());
              assertEquals(expectedOperation.getFromStatus(), operation.getFromStatus());
              assertEquals(expectedOperation getFromStatus() operation getFromStatus());
              assertEquals(expectedOperation.getToStatus(), operation.getToStatus());
              assertFalse(operation.getTimestamp().before(startTime));
              assertFalse(operation.getTimestamp().after(endTime));
            }




3/1/2009                                                                                       51
                                   Copyright (c) 2007 Chris Richardson. All rights reserved.
Literate assertions with Hamcrest
    Hamcrest is an open-source framework
    http://code.google.com/p/hamcrest/
    Readable quot;literatequot; assertions
    Rich set of composable matchers
    Literate error messages
    Used by Jmock expectations
  import static org.hamcrest.MatcherAssert.assertThat;
  import static org.hamcrest.Matchers.is;
                org hamcrest Matchers is;
  import static org.hamcrest.Matchers.isOneOf;

   assertThat(project.getStatus(), is(state1));
   assertThat(project.getStatus(), isOneOf(state1, state2));
   assertThat(project.getStatus(), allOf(is(state), not(is(state2))));
        tTh t(   jt     tSt t () llOf(i ( t t )       t(i ( t t 2))))


3/1/2009                                                                                 52
                             Copyright (c) 2007 Chris Richardson. All rights reserved.
Hamcrest custom matchers
public class ProjectMatchers {

 p
 public static Matcher<Date> withinInclusivePeriod(final Date startTime,
                                                  (                    ,
    final Date endTime) {
   return new TypeSafeMatcher<Date>() {

     public boolean matchesSafely(Date date) {
       return !date.before(startTime) && !date.after(endTime);
     }

     public void describeTo(Description description) {
       description.appendText(String.format(quot;expected to be between <%s> and <%s>quot;,
         startTime, endTime));
     }
           import static org.jia.ptrack.domain.ProjectMatchers.withinInclusivePeriod;
             p             gj p                   j                                 ;
    };
}          public void testChangeStatus() {

            assertThat(operation.getTimestamp(),
                        is(withinInclusivePeriod(startTime, endTime)));
           }
                          java.lang.AssertionError:
                          Expected: is expected to be between <Wed Nov 14 19:39:23 PST 2007> and
                          <Wed Nov 14 19:39:23 PST 2007>
                              got: <Wed Dec 31 16:00:00 PST 1969>
                                        at
                          org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:21)
                            g                                    (            j      )




3/1/2009                                                                                           53
                                      Copyright (c) 2007 Chris Richardson. All rights reserved.
Agenda
 g
    Introduction
    Testing services
    Testing entities and value objects
          g                       j
    Taming test fixture logic
    Simplifying verification code
    Writing more meaningful tests




3/1/2009                                                                   54
               Copyright (c) 2007 Chris Richardson. All rights reserved.
TDD says begin with a test but…


                                                  Daddy, where do
                                                  tests come from?




3/1/2009                                                               55
           Copyright (c) 2007 Chris Richardson. All rights reserved.
Best to derive tests from
     requirements
       q
    As a customer of the bank
    I want to transfer money between two bank accounts
    So that I don't have to write a check

                                                                  class AccountTransferServiceTests … {

                                                                   public void testTransfer_ok() {
                                                                     Account savingsAccount =
                                                                                 AccountMother.makeAccountWithNoOverdraft(150);
                                                                     Account checkingAccount =
Given that my savings account balance is $150                                    AccountMother.makeAccountWithNoOverdraft(10);
Given that my checking account balance is $10                        String savingsAccountId = savingsAccount.getAccountId();
When I transfer $50 from my savings account                          String checkingAccountId = checkingAccount.getAccountId();
       to my checking account                                        repository.addAccount(savingsAccount);
Then my savings account balance is $100                              repository.addAccount(checkingAccount);
                                                                       p      y             (      g       );
Then my checking account balance is $60
                                                                        service.transfer(savingsAccountId, checkingAccountId, 50);

                                                                        assertBalance(100, savingsAccountId);
                                                                        assertBalance(60, checkingAccountId);

                                                                    }
Given that my savings account balance is $150
Given that my checking account balance is $10
                                                                    public void testTransfer_overdraftAttempted() {
Given that my bank does not allow me
                                                                      ….
   to have an overdraft
                                                                    }
When I transfer $200 from my savings account
   to my checking account
        y       g
Then my savings account balance is unchanged
Then my checking account balance is unchanged


      3/1/2009                                                                                                               56
                                           Copyright (c) 2007 Chris Richardson. All rights reserved.
Testing at multiple levels
      g         p
    Where in the hierarchy to write a test?
           Web tier
           Service integration test
           Mock service test
           Entity/Value object test
    Sometimes at every level
           Few high-level tests, e g verify that the UI
                           tests e.g.
           handles errors
           Many lower-level, more detailed tests, e.g. tests
           for each error scenario
    Sometimes only lower-level tests
           E.g. verifying that email is sent after
           transferring money ⇒ mock object service test
                fi                     k bj        i

3/1/2009                                                                           57
                       Copyright (c) 2007 Chris Richardson. All rights reserved.
We sometimes invent requirements
                      q
    User requirements focus on the external
    behavior:
           Behavior of boundary classes, i.e. UI +
           services
           Key domain model classes, e.g. account
    But those classes often have
    collaborators:
           E.g. Account has CalendarDate
    When designing those classes:
           Informally specify the behavior of those
           classes
           Write capture that behavior in tests
3/1/2009                                                                          58
                      Copyright (c) 2007 Chris Richardson. All rights reserved.
More formal testing
                  g

                                                     1000+ pages of
                                                     rigorous testing
                                                     techniques




3/1/2009                                                                59
           Copyright (c) 2007 Chris Richardson. All rights reserved.
Deriving tests from a state machine
model
                                                                   • State machine is a useful way
                                                                   to model some classes (and
                                                                                            (
                       r

                                                                   UIs)
                                                                   • N+ test strategy
                                                                       • Turn state machine into a
               p           q
       A           B                   C
                                                                       tree containing all edges
                                                                       • Test cases = paths to all
                                                                       leaves
           s

                                                                       •Test = sequence of events

                                                                                       public testPQR() {
                                                                                       }

                                                                                       public testPS() {
                                                                                       }




3/1/2009                                                                                             60
                           Copyright (c) 2007 Chris Richardson. All rights reserved.
Deriving tests from boolean
expressions
  p

           Class invariant/function/conditional: (x >= 1 & y < 10)


Variable    Condition                             Test #1                   #2           #3      #4

x           X >= 1
              >         On                        1

                        Off                                                 0

                        Typical                                                          10      10

Y           Y < 10      On                                                               10

                        Off                                                                      9

                        Typical                   2                         2

Result                                            True                      False        False   True



              1x1 selection criteria


3/1/2009                                                                                                61
                             Copyright (c) 2007 Chris Richardson. All rights reserved.
Derive tests from code
    Write tests to improve
    code coverageg
    Identifies
    behavior/edge cases
    that you forgot to test
    Characterization tests:
           Capture current
           behavior
           Useful for refactoring
           (sometimes)
           But they can be brittle
                                                                       Tip: Use a code coverage
    Code might not be                                                  tool: Cobertura (f
                                                                       t l Cb t        (free),
                                                                                            )
    correct!                                                           Clover (cheap), …




3/1/2009                                                                                      62
                        Copyright (c) 2007 Chris Richardson. All rights reserved.
Use code metrics to identify what
to test
    Cyclomatic
    complexity
           Bugs lurk here
           Simplify if you can
    Large methods
    L       th d
           Bugs lurk in here also
           Simplify if you can
    Crap4J
    (www.crap4j.org)
           Computes code
           quality by combining
           code coverage and
           complexity

3/1/2009                                                                          63
                      Copyright (c) 2007 Chris Richardson. All rights reserved.
Summary
      y
    Testing is essential
    Use mock objects to accelerate tests
    Aggressively refactor tests to keep
     gg         y                     p
    them simple
    Use Object Mothers to avoid
           j
    duplication of test fixture logic
    Simplify assertions
    Derive tests from requirements


3/1/2009                                                                   64
               Copyright (c) 2007 Chris Richardson. All rights reserved.
For more information

                                                     Buy my book ☺
                                                               Go to manning.com

                                                     Send email:

                                           chris@chrisrichardson.net

                                                     Visit my website:

                                           http://www.chrisrichardson.
                                               net

                                                     Talk to me about
                                                     consulting and training


3/1/2009                                                                           65
           Copyright (c) 2007 Chris Richardson. All rights reserved.

More Related Content

What's hot

Spring Framework - Core
Spring Framework - CoreSpring Framework - Core
Spring Framework - Core
Dzmitry Naskou
 
Angular Basics.pptx
Angular Basics.pptxAngular Basics.pptx
Angular Basics.pptx
AshokKumar616995
 
D2 domain driven-design
D2 domain driven-designD2 domain driven-design
D2 domain driven-design
Arnaud Bouchez
 
DDD Strategic Design - Context Maps - Paulo Clavijo - April 2018
DDD Strategic Design - Context Maps - Paulo Clavijo - April 2018DDD Strategic Design - Context Maps - Paulo Clavijo - April 2018
DDD Strategic Design - Context Maps - Paulo Clavijo - April 2018
Paulo Clavijo
 
Applying Domain-Driven Design to craft Rich Domain Models
Applying Domain-Driven Design to craft Rich Domain ModelsApplying Domain-Driven Design to craft Rich Domain Models
Applying Domain-Driven Design to craft Rich Domain Models
Alexander van Trijffel
 
Event Storming and Saga
Event Storming and SagaEvent Storming and Saga
Event Storming and Saga
Araf Karsh Hamid
 
Building Rich Domain Models
Building Rich Domain ModelsBuilding Rich Domain Models
Building Rich Domain Models
Chris Richardson
 
Retour opérationnel sur la clean architecture
Retour opérationnel sur la clean architectureRetour opérationnel sur la clean architecture
Retour opérationnel sur la clean architecture
RomainKuzniak
 
Clean architecture on android
Clean architecture on androidClean architecture on android
Clean architecture on android
Benjamin Cheng
 
Spring batch
Spring batchSpring batch
Spring batch
Chandan Kumar Rana
 
Kotlin Jetpack Tutorial
Kotlin Jetpack TutorialKotlin Jetpack Tutorial
Kotlin Jetpack Tutorial
Simplilearn
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven Design
Hannah Farrugia
 
Ngrx: Redux in angular
Ngrx: Redux in angularNgrx: Redux in angular
Ngrx: Redux in angular
Saadnoor Salehin
 
Domain driven design: a gentle introduction
Domain driven design:  a gentle introductionDomain driven design:  a gentle introduction
Domain driven design: a gentle introduction
Asher Sterkin
 
Kata: Hexagonal Architecture / Ports and Adapters
Kata: Hexagonal Architecture / Ports and AdaptersKata: Hexagonal Architecture / Ports and Adapters
Kata: Hexagonal Architecture / Ports and Adapters
holsky
 
DDD Introduction
DDD IntroductionDDD Introduction
DDD Introduction
Gregory Boissinot
 
REST APIs with Spring
REST APIs with SpringREST APIs with Spring
REST APIs with Spring
Joshua Long
 
React state managmenet with Redux
React state managmenet with ReduxReact state managmenet with Redux
React state managmenet with Redux
Vedran Blaženka
 
Introduction to react and redux
Introduction to react and reduxIntroduction to react and redux
Introduction to react and redux
Cuong Ho
 

What's hot (20)

Spring Framework - Core
Spring Framework - CoreSpring Framework - Core
Spring Framework - Core
 
Angular Basics.pptx
Angular Basics.pptxAngular Basics.pptx
Angular Basics.pptx
 
D2 domain driven-design
D2 domain driven-designD2 domain driven-design
D2 domain driven-design
 
DDD Strategic Design - Context Maps - Paulo Clavijo - April 2018
DDD Strategic Design - Context Maps - Paulo Clavijo - April 2018DDD Strategic Design - Context Maps - Paulo Clavijo - April 2018
DDD Strategic Design - Context Maps - Paulo Clavijo - April 2018
 
Applying Domain-Driven Design to craft Rich Domain Models
Applying Domain-Driven Design to craft Rich Domain ModelsApplying Domain-Driven Design to craft Rich Domain Models
Applying Domain-Driven Design to craft Rich Domain Models
 
Event Storming and Saga
Event Storming and SagaEvent Storming and Saga
Event Storming and Saga
 
Building Rich Domain Models
Building Rich Domain ModelsBuilding Rich Domain Models
Building Rich Domain Models
 
Retour opérationnel sur la clean architecture
Retour opérationnel sur la clean architectureRetour opérationnel sur la clean architecture
Retour opérationnel sur la clean architecture
 
Clean architecture on android
Clean architecture on androidClean architecture on android
Clean architecture on android
 
Spring batch
Spring batchSpring batch
Spring batch
 
Kotlin Jetpack Tutorial
Kotlin Jetpack TutorialKotlin Jetpack Tutorial
Kotlin Jetpack Tutorial
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven Design
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven Design
 
Ngrx: Redux in angular
Ngrx: Redux in angularNgrx: Redux in angular
Ngrx: Redux in angular
 
Domain driven design: a gentle introduction
Domain driven design:  a gentle introductionDomain driven design:  a gentle introduction
Domain driven design: a gentle introduction
 
Kata: Hexagonal Architecture / Ports and Adapters
Kata: Hexagonal Architecture / Ports and AdaptersKata: Hexagonal Architecture / Ports and Adapters
Kata: Hexagonal Architecture / Ports and Adapters
 
DDD Introduction
DDD IntroductionDDD Introduction
DDD Introduction
 
REST APIs with Spring
REST APIs with SpringREST APIs with Spring
REST APIs with Spring
 
React state managmenet with Redux
React state managmenet with ReduxReact state managmenet with Redux
React state managmenet with Redux
 
Introduction to react and redux
Introduction to react and reduxIntroduction to react and redux
Introduction to react and redux
 

Viewers also liked

Introduction repository, ddd and unit test
Introduction repository, ddd and unit testIntroduction repository, ddd and unit test
Introduction repository, ddd and unit test
Hiraq Citra M
 
From ActiveRecord to EventSourcing
From ActiveRecord to EventSourcingFrom ActiveRecord to EventSourcing
From ActiveRecord to EventSourcing
Emanuele DelBono
 
IoC&Laravel
IoC&LaravelIoC&Laravel
IoC&Laravel
Hoang Long
 
Proved PHP Design Patterns for Data Persistence
Proved PHP Design Patterns for Data PersistenceProved PHP Design Patterns for Data Persistence
Proved PHP Design Patterns for Data Persistence
Gjero Krsteski
 
The Long Sad History of MicroServices (Greg Young Technology Stream)
The Long Sad History of MicroServices (Greg Young Technology Stream)The Long Sad History of MicroServices (Greg Young Technology Stream)
The Long Sad History of MicroServices (Greg Young Technology Stream)
IT Arena
 
Repository design pattern in laravel - Samir Poudel
Repository design pattern in laravel - Samir PoudelRepository design pattern in laravel - Samir Poudel
Repository design pattern in laravel - Samir Poudel
Sameer Poudel
 
Drools Workshop @JBCNCONF 2016
Drools Workshop @JBCNCONF 2016Drools Workshop @JBCNCONF 2016
Drools Workshop @JBCNCONF 2016
Mauricio (Salaboy) Salatino
 
A People's History of Microservices
A People's History of MicroservicesA People's History of Microservices
A People's History of Microservices
Camille Fournier
 
Intelligent Business Process Management Suites (iBPMS) - The Next-Generation ...
Intelligent Business Process Management Suites (iBPMS) - The Next-Generation ...Intelligent Business Process Management Suites (iBPMS) - The Next-Generation ...
Intelligent Business Process Management Suites (iBPMS) - The Next-Generation ...
Kai Wähner
 
Domain Driven Design using Laravel
Domain Driven Design using LaravelDomain Driven Design using Laravel
Domain Driven Design using Laravel
wajrcs
 
TEDx Manchester: AI & The Future of Work
TEDx Manchester: AI & The Future of WorkTEDx Manchester: AI & The Future of Work
TEDx Manchester: AI & The Future of Work
Volker Hirsch
 

Viewers also liked (11)

Introduction repository, ddd and unit test
Introduction repository, ddd and unit testIntroduction repository, ddd and unit test
Introduction repository, ddd and unit test
 
From ActiveRecord to EventSourcing
From ActiveRecord to EventSourcingFrom ActiveRecord to EventSourcing
From ActiveRecord to EventSourcing
 
IoC&Laravel
IoC&LaravelIoC&Laravel
IoC&Laravel
 
Proved PHP Design Patterns for Data Persistence
Proved PHP Design Patterns for Data PersistenceProved PHP Design Patterns for Data Persistence
Proved PHP Design Patterns for Data Persistence
 
The Long Sad History of MicroServices (Greg Young Technology Stream)
The Long Sad History of MicroServices (Greg Young Technology Stream)The Long Sad History of MicroServices (Greg Young Technology Stream)
The Long Sad History of MicroServices (Greg Young Technology Stream)
 
Repository design pattern in laravel - Samir Poudel
Repository design pattern in laravel - Samir PoudelRepository design pattern in laravel - Samir Poudel
Repository design pattern in laravel - Samir Poudel
 
Drools Workshop @JBCNCONF 2016
Drools Workshop @JBCNCONF 2016Drools Workshop @JBCNCONF 2016
Drools Workshop @JBCNCONF 2016
 
A People's History of Microservices
A People's History of MicroservicesA People's History of Microservices
A People's History of Microservices
 
Intelligent Business Process Management Suites (iBPMS) - The Next-Generation ...
Intelligent Business Process Management Suites (iBPMS) - The Next-Generation ...Intelligent Business Process Management Suites (iBPMS) - The Next-Generation ...
Intelligent Business Process Management Suites (iBPMS) - The Next-Generation ...
 
Domain Driven Design using Laravel
Domain Driven Design using LaravelDomain Driven Design using Laravel
Domain Driven Design using Laravel
 
TEDx Manchester: AI & The Future of Work
TEDx Manchester: AI & The Future of WorkTEDx Manchester: AI & The Future of Work
TEDx Manchester: AI & The Future of Work
 

Similar to Testing Rich Domain Models

Flex For Java Developers - SDForum Java SIG
Flex For Java Developers - SDForum Java SIGFlex For Java Developers - SDForum Java SIG
Flex For Java Developers - SDForum Java SIG
Chris Richardson
 
[Infosecworld 08 Orlando] New Defenses for .NET Web Apps: IHttpModule in Prac...
[Infosecworld 08 Orlando] New Defenses for .NET Web Apps: IHttpModule in Prac...[Infosecworld 08 Orlando] New Defenses for .NET Web Apps: IHttpModule in Prac...
[Infosecworld 08 Orlando] New Defenses for .NET Web Apps: IHttpModule in Prac...Shreeraj Shah
 
Salesforce & SAP Integration
Salesforce & SAP IntegrationSalesforce & SAP Integration
Salesforce & SAP Integration
Raymond Gao
 
08 Ace 2010 Aras Roadmap
08 Ace 2010 Aras Roadmap08 Ace 2010 Aras Roadmap
08 Ace 2010 Aras Roadmap
Prodeos
 
CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...
CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...
CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...
Chris Richardson
 
Aras Innovator PLM Deployment Methodology
Aras Innovator PLM Deployment MethodologyAras Innovator PLM Deployment Methodology
Aras Innovator PLM Deployment MethodologyAras
 
20110507 Implementing Continuous Deployment
20110507 Implementing Continuous Deployment20110507 Implementing Continuous Deployment
20110507 Implementing Continuous Deployment
XebiaLabs
 
Software Development Engineers Ireland
Software Development Engineers IrelandSoftware Development Engineers Ireland
Software Development Engineers Ireland
Sean O'Sullivan
 
Enterprise Mashups With Soa
Enterprise Mashups With SoaEnterprise Mashups With Soa
Enterprise Mashups With Soa
umityalcinalp
 
A Data Scientist And A Log File Walk Into A Bar...
A Data Scientist And A Log File Walk Into A Bar...A Data Scientist And A Log File Walk Into A Bar...
A Data Scientist And A Log File Walk Into A Bar...
Paco Nathan
 
Business processes, business rules, complex event processing, the JBoss way
Business processes, business rules, complex event processing, the JBoss wayBusiness processes, business rules, complex event processing, the JBoss way
Business processes, business rules, complex event processing, the JBoss way
Kris Verlaenen
 
Developing modular, polyglot applications with Spring (SpringOne India 2012)
Developing modular, polyglot applications with Spring (SpringOne India 2012)Developing modular, polyglot applications with Spring (SpringOne India 2012)
Developing modular, polyglot applications with Spring (SpringOne India 2012)Chris Richardson
 
Best Practices Europe 10 Steps To Successful Deployments
Best Practices Europe 10 Steps To Successful DeploymentsBest Practices Europe 10 Steps To Successful Deployments
Best Practices Europe 10 Steps To Successful Deployments
Joel Oleson
 
Dirk Krafzig Enterprise S O Aand Dependency Mngt
Dirk  Krafzig    Enterprise S O Aand Dependency MngtDirk  Krafzig    Enterprise S O Aand Dependency Mngt
Dirk Krafzig Enterprise S O Aand Dependency MngtSOA Symposium
 
Sipoc
SipocSipoc
Sipoc
dhruv_shah
 
Module 3 Adapative Customer Experience Final
Module 3 Adapative Customer Experience FinalModule 3 Adapative Customer Experience Final
Module 3 Adapative Customer Experience FinalVivastream
 
Ian Robinson Testable Foundations
Ian  Robinson    Testable  FoundationsIan  Robinson    Testable  Foundations
Ian Robinson Testable FoundationsSOA Symposium
 
Framework Engineering_Final
Framework Engineering_FinalFramework Engineering_Final
Framework Engineering_FinalYoungSu Son
 
IdealECP presentation for Novo Nordisk
IdealECP presentation for Novo NordiskIdealECP presentation for Novo Nordisk
IdealECP presentation for Novo Nordiskcbiddle2
 

Similar to Testing Rich Domain Models (20)

Default
DefaultDefault
Default
 
Flex For Java Developers - SDForum Java SIG
Flex For Java Developers - SDForum Java SIGFlex For Java Developers - SDForum Java SIG
Flex For Java Developers - SDForum Java SIG
 
[Infosecworld 08 Orlando] New Defenses for .NET Web Apps: IHttpModule in Prac...
[Infosecworld 08 Orlando] New Defenses for .NET Web Apps: IHttpModule in Prac...[Infosecworld 08 Orlando] New Defenses for .NET Web Apps: IHttpModule in Prac...
[Infosecworld 08 Orlando] New Defenses for .NET Web Apps: IHttpModule in Prac...
 
Salesforce & SAP Integration
Salesforce & SAP IntegrationSalesforce & SAP Integration
Salesforce & SAP Integration
 
08 Ace 2010 Aras Roadmap
08 Ace 2010 Aras Roadmap08 Ace 2010 Aras Roadmap
08 Ace 2010 Aras Roadmap
 
CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...
CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...
CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...
 
Aras Innovator PLM Deployment Methodology
Aras Innovator PLM Deployment MethodologyAras Innovator PLM Deployment Methodology
Aras Innovator PLM Deployment Methodology
 
20110507 Implementing Continuous Deployment
20110507 Implementing Continuous Deployment20110507 Implementing Continuous Deployment
20110507 Implementing Continuous Deployment
 
Software Development Engineers Ireland
Software Development Engineers IrelandSoftware Development Engineers Ireland
Software Development Engineers Ireland
 
Enterprise Mashups With Soa
Enterprise Mashups With SoaEnterprise Mashups With Soa
Enterprise Mashups With Soa
 
A Data Scientist And A Log File Walk Into A Bar...
A Data Scientist And A Log File Walk Into A Bar...A Data Scientist And A Log File Walk Into A Bar...
A Data Scientist And A Log File Walk Into A Bar...
 
Business processes, business rules, complex event processing, the JBoss way
Business processes, business rules, complex event processing, the JBoss wayBusiness processes, business rules, complex event processing, the JBoss way
Business processes, business rules, complex event processing, the JBoss way
 
Developing modular, polyglot applications with Spring (SpringOne India 2012)
Developing modular, polyglot applications with Spring (SpringOne India 2012)Developing modular, polyglot applications with Spring (SpringOne India 2012)
Developing modular, polyglot applications with Spring (SpringOne India 2012)
 
Best Practices Europe 10 Steps To Successful Deployments
Best Practices Europe 10 Steps To Successful DeploymentsBest Practices Europe 10 Steps To Successful Deployments
Best Practices Europe 10 Steps To Successful Deployments
 
Dirk Krafzig Enterprise S O Aand Dependency Mngt
Dirk  Krafzig    Enterprise S O Aand Dependency MngtDirk  Krafzig    Enterprise S O Aand Dependency Mngt
Dirk Krafzig Enterprise S O Aand Dependency Mngt
 
Sipoc
SipocSipoc
Sipoc
 
Module 3 Adapative Customer Experience Final
Module 3 Adapative Customer Experience FinalModule 3 Adapative Customer Experience Final
Module 3 Adapative Customer Experience Final
 
Ian Robinson Testable Foundations
Ian  Robinson    Testable  FoundationsIan  Robinson    Testable  Foundations
Ian Robinson Testable Foundations
 
Framework Engineering_Final
Framework Engineering_FinalFramework Engineering_Final
Framework Engineering_Final
 
IdealECP presentation for Novo Nordisk
IdealECP presentation for Novo NordiskIdealECP presentation for Novo Nordisk
IdealECP presentation for Novo Nordisk
 

More from Chris Richardson

The microservice architecture: what, why, when and how?
The microservice architecture: what, why, when and how?The microservice architecture: what, why, when and how?
The microservice architecture: what, why, when and how?
Chris Richardson
 
More the merrier: a microservices anti-pattern
More the merrier: a microservices anti-patternMore the merrier: a microservices anti-pattern
More the merrier: a microservices anti-pattern
Chris Richardson
 
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...
Chris Richardson
 
Dark Energy, Dark Matter and the Microservices Patterns?!
Dark Energy, Dark Matter and the Microservices Patterns?!Dark Energy, Dark Matter and the Microservices Patterns?!
Dark Energy, Dark Matter and the Microservices Patterns?!
Chris Richardson
 
Dark energy, dark matter and microservice architecture collaboration patterns
Dark energy, dark matter and microservice architecture collaboration patternsDark energy, dark matter and microservice architecture collaboration patterns
Dark energy, dark matter and microservice architecture collaboration patterns
Chris Richardson
 
Scenarios_and_Architecture_SkillsMatter_April_2022.pdf
Scenarios_and_Architecture_SkillsMatter_April_2022.pdfScenarios_and_Architecture_SkillsMatter_April_2022.pdf
Scenarios_and_Architecture_SkillsMatter_April_2022.pdf
Chris Richardson
 
Using patterns and pattern languages to make better architectural decisions
Using patterns and pattern languages to make better architectural decisions Using patterns and pattern languages to make better architectural decisions
Using patterns and pattern languages to make better architectural decisions
Chris Richardson
 
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...
Chris Richardson
 
Events to the rescue: solving distributed data problems in a microservice arc...
Events to the rescue: solving distributed data problems in a microservice arc...Events to the rescue: solving distributed data problems in a microservice arc...
Events to the rescue: solving distributed data problems in a microservice arc...
Chris Richardson
 
A pattern language for microservices - June 2021
A pattern language for microservices - June 2021 A pattern language for microservices - June 2021
A pattern language for microservices - June 2021
Chris Richardson
 
QConPlus 2021: Minimizing Design Time Coupling in a Microservice Architecture
QConPlus 2021: Minimizing Design Time Coupling in a Microservice ArchitectureQConPlus 2021: Minimizing Design Time Coupling in a Microservice Architecture
QConPlus 2021: Minimizing Design Time Coupling in a Microservice Architecture
Chris Richardson
 
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...
Chris Richardson
 
Designing loosely coupled services
Designing loosely coupled servicesDesigning loosely coupled services
Designing loosely coupled services
Chris Richardson
 
Microservices - an architecture that enables DevOps (T Systems DevOps day)
Microservices - an architecture that enables DevOps (T Systems DevOps day)Microservices - an architecture that enables DevOps (T Systems DevOps day)
Microservices - an architecture that enables DevOps (T Systems DevOps day)
Chris Richardson
 
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...
Chris Richardson
 
Decompose your monolith: Six principles for refactoring a monolith to microse...
Decompose your monolith: Six principles for refactoring a monolith to microse...Decompose your monolith: Six principles for refactoring a monolith to microse...
Decompose your monolith: Six principles for refactoring a monolith to microse...
Chris Richardson
 
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...
Chris Richardson
 
Overview of the Eventuate Tram Customers and Orders application
Overview of the Eventuate Tram Customers and Orders applicationOverview of the Eventuate Tram Customers and Orders application
Overview of the Eventuate Tram Customers and Orders application
Chris Richardson
 
An overview of the Eventuate Platform
An overview of the Eventuate PlatformAn overview of the Eventuate Platform
An overview of the Eventuate Platform
Chris Richardson
 
#DevNexus202 Decompose your monolith
#DevNexus202 Decompose your monolith#DevNexus202 Decompose your monolith
#DevNexus202 Decompose your monolith
Chris Richardson
 

More from Chris Richardson (20)

The microservice architecture: what, why, when and how?
The microservice architecture: what, why, when and how?The microservice architecture: what, why, when and how?
The microservice architecture: what, why, when and how?
 
More the merrier: a microservices anti-pattern
More the merrier: a microservices anti-patternMore the merrier: a microservices anti-pattern
More the merrier: a microservices anti-pattern
 
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...
 
Dark Energy, Dark Matter and the Microservices Patterns?!
Dark Energy, Dark Matter and the Microservices Patterns?!Dark Energy, Dark Matter and the Microservices Patterns?!
Dark Energy, Dark Matter and the Microservices Patterns?!
 
Dark energy, dark matter and microservice architecture collaboration patterns
Dark energy, dark matter and microservice architecture collaboration patternsDark energy, dark matter and microservice architecture collaboration patterns
Dark energy, dark matter and microservice architecture collaboration patterns
 
Scenarios_and_Architecture_SkillsMatter_April_2022.pdf
Scenarios_and_Architecture_SkillsMatter_April_2022.pdfScenarios_and_Architecture_SkillsMatter_April_2022.pdf
Scenarios_and_Architecture_SkillsMatter_April_2022.pdf
 
Using patterns and pattern languages to make better architectural decisions
Using patterns and pattern languages to make better architectural decisions Using patterns and pattern languages to make better architectural decisions
Using patterns and pattern languages to make better architectural decisions
 
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...
 
Events to the rescue: solving distributed data problems in a microservice arc...
Events to the rescue: solving distributed data problems in a microservice arc...Events to the rescue: solving distributed data problems in a microservice arc...
Events to the rescue: solving distributed data problems in a microservice arc...
 
A pattern language for microservices - June 2021
A pattern language for microservices - June 2021 A pattern language for microservices - June 2021
A pattern language for microservices - June 2021
 
QConPlus 2021: Minimizing Design Time Coupling in a Microservice Architecture
QConPlus 2021: Minimizing Design Time Coupling in a Microservice ArchitectureQConPlus 2021: Minimizing Design Time Coupling in a Microservice Architecture
QConPlus 2021: Minimizing Design Time Coupling in a Microservice Architecture
 
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...
 
Designing loosely coupled services
Designing loosely coupled servicesDesigning loosely coupled services
Designing loosely coupled services
 
Microservices - an architecture that enables DevOps (T Systems DevOps day)
Microservices - an architecture that enables DevOps (T Systems DevOps day)Microservices - an architecture that enables DevOps (T Systems DevOps day)
Microservices - an architecture that enables DevOps (T Systems DevOps day)
 
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...
 
Decompose your monolith: Six principles for refactoring a monolith to microse...
Decompose your monolith: Six principles for refactoring a monolith to microse...Decompose your monolith: Six principles for refactoring a monolith to microse...
Decompose your monolith: Six principles for refactoring a monolith to microse...
 
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...
 
Overview of the Eventuate Tram Customers and Orders application
Overview of the Eventuate Tram Customers and Orders applicationOverview of the Eventuate Tram Customers and Orders application
Overview of the Eventuate Tram Customers and Orders application
 
An overview of the Eventuate Platform
An overview of the Eventuate PlatformAn overview of the Eventuate Platform
An overview of the Eventuate Platform
 
#DevNexus202 Decompose your monolith
#DevNexus202 Decompose your monolith#DevNexus202 Decompose your monolith
#DevNexus202 Decompose your monolith
 

Recently uploaded

FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance
 
"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi
Fwdays
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
Guy Korland
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
Laura Byrne
 
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMsTo Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
Paul Groth
 
UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3
DianaGray10
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
Ralf Eggert
 
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Product School
 
Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
DianaGray10
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance
 
ODC, Data Fabric and Architecture User Group
ODC, Data Fabric and Architecture User GroupODC, Data Fabric and Architecture User Group
ODC, Data Fabric and Architecture User Group
CatarinaPereira64715
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
Thijs Feryn
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Product School
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Inflectra
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
Product School
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
BookNet Canada
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
Alan Dix
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
James Anderson
 
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 previewState of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
Prayukth K V
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
Cheryl Hung
 

Recently uploaded (20)

FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
 
"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
 
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMsTo Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
 
UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
 
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
 
Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
 
ODC, Data Fabric and Architecture User Group
ODC, Data Fabric and Architecture User GroupODC, Data Fabric and Architecture User Group
ODC, Data Fabric and Architecture User Group
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
 
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 previewState of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
 

Testing Rich Domain Models

  • 1. Testing Rich Domain Models Chris i h d Ch i Richardson Author of POJOs in Action Chris Richardson C Ch i Ri h d Consulting, I lti Inc http://www.chrisrichardson.net 3/1/2009 1 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 2. Overview Testing a rich g domain model: Why? How? 3/1/2009 2 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 3. About Chris Grew up in England Live in Oakland, CA Over twenty years of software development experience Building object-oriented g j software since 1986 Using Java since 1996 Using J2EE since 1999 Author of POJOs in Action Speaker at JavaOne, JavaPolis, SpringOne, NFJS, JUGs, …. Chair of the eBIG Java SIG in Oakland (www.ebig.org) Run a consulting and training company that helps organizations build better software faster 3/1/2009 3 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 4. Agenda g Introduction Testing services Testing entities and value objects g j Taming test fixture logic Simplifying verification code Writing more meaningful tests 3/1/2009 4 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 5. Using the Domain Model Pattern g Traditional enterprise Java applications: Business l i i f t service Bi logic in fat i Services manipulate dumb Java beans Doesn t Doesn't handle complexity Domain model pattern: Business logic spread amongst a collection of classes fl Many classes are true objects having both state (fields) and behavior ( ( ) (methods) the ) state Many classes correspond to real world concepts: Order Customer, … Order, Customer 3/1/2009 5 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 6. Procedural versus OO Presentation Tier Presentation Tier Business Tier Business Tier Transaction Scripts Facade (Session Beans) Domain Model Data Objects Obj Data Access Tier Data Access Tier 3/1/2009 6 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 7. An example domain model p Web Tier Behavior Business Tier MoneyTransferService BankingTransaction transfer(fromId, toId, amount) from Account Banking Account BankingTransaction Transaction Repository Repository balance to amount findAccount(id) addTransaction(…) debit(amount) date credit(amount) Explicit <<interface>> OverdraftPolicy Representation State + of key Behavior Limited concepts p NoOverdraft Overdraft Policy y limit 3/1/2009 7 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 8. Why test? y Write new code more easily Automates what we are doing already - Right!? Run fast unit tests instead of slower web application pp Use TDD to incrementally solve a problem Tests are a safety net y Confidently change existing code Easier to refactor code to prevent decay The application has longer, healthier life Fewer bugs that impact customers g p AND development 3/1/2009 8 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 9. Why test a domain model? y Benefits of pushing tests down p g the hierarchy: Easier and cheaper Faster Better error localization You change a complex interest calculation: How do you want to test it: Through a changing GUI? With simple unit tests When do you want to find out whether it works? 15 minutes later after running web tests? 10 seconds later after running hundreds of unit tests? Determining why a test fails? Because of a problem with the database or UI? Because the algorithm was wrong? 3/1/2009 9 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 10. Domain models make testing easier g More modular: Smaller classes/methods that are easier to test Business l i i i logic implemented b l d by immutable value objects Functions are easier to test that code h d with side-effects Back to basics - POJOs with no dependencies on infrastructure Quickly test in isolation 3/1/2009 10 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 11. Domain models make testing more difficult… Domain models are often used when the business logic is complex Objects are structurally more complex Not relational – i.e. not flat, coarse-grained Finer grained objects, i.e. many classes map to the same table) Richer relationships between objects Deeper object graphs Object behavior is more complex Behavior determined by collaborators + internal state (reflects previous method invocations) Classes are often modal: imposes ordering on method invocations 3/1/2009 11 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 12. …Domain models make testing more difficult Richer collaborations Service does more than invoke getters and setters on domain objects Domain objects invoke methods on one another Encapsulation p Domain Objects != JavaBeans Perhaps getters but preferably not setters Initializing objects is more complex Verifying object state might be more difficult 3/1/2009 12 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 13. Excellent testing book g Test smells and how to fix them Obscure test Fragile test Test code duplication … Comprehensive pattern C h i tt language: Four phase test Minimal fixture Test utility method Test helper Humble Object … 3/1/2009 13 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 14. Agenda g Introduction Testing services Testing entities and value objects g j Taming test fixture logic Simplifying verification code Writing more meaningful tests 3/1/2009 14 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 15. What's a Service? A role that some domain public interface MoneyTransferService { model classes play BankingTransaction transfer(String fromAccountId, String toAccountId, double amount) Implements logic that throws MoneyTransferException; cannot be put in a single } entity Not N t persistent it t public class MoneyTransferServiceImpl implements MoneyTransferService { Consists of an interface and an implementation private final AccountRepository accountRepository; class private final BankingTransactionRepository bankingTransactionRepository; Service method usually: Invoked (indirectly) by public MoneyTransferServiceImpl(AccountRepository accountRepository, BankingTransactionRepository bankingTransactionRepository) { presentation tier this.accountRepository = accountRepository; Invokes one or more this.bankingTransactionRepository = bankingTransactionRepository; repositories } Invokes one or more entities public B ki T bli BankingTransaction t ti transfer(String f f (St i fromAccountId, A tId Well-designed services String toAccountId, double amount) { … are thin fromAccount.debit(amount); toAccount.credit(amount); Improves code quality … Makes them easier to test } } 3/1/2009 15 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 16. How to test a service? p public class MoneyTransferServiceImpl implements MoneyTransferService { y p p y private final AccountRepository accountRepository; private final BankingTransactionRepository bankingTransactionRepository; public MoneyTransferServiceImpl(AccountRepository accountRepository, BankingTransactionRepository b ki ki i i bankingTransactionRepository) { i i ) this.accountRepository = accountRepository; this.bankingTransactionRepository = bankingTransactionRepository; } public BankingTransaction transfer(String fromAccountId fromAccountId, String toAccountId, double amount) throws MoneyTransferException { Account fromAccount = accountRepository.findAccount(fromAccountId); Account toAccount = accountRepository.findAccount(toAccountId); fromAccount.debit(amount); toAccount.credit(amount); TransferTransaction txn = new TransferTransaction(fromAccount, toAccount, amount, new Date()); bankingTransactionRepository.addTransaction(txn); return txn; Database access } … 3/1/2009 16 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 17. Writing service integration tests Fixture logic: public class SpringMoneyTransferServiceTests extends AbstractDependencyInjectionSpringContextTests { … Creates service @Override protected String[] getConfigLocations() { return new String[] { quot;classpath:/appCtx/*.xmlquot; }; Initializes database } Exercise phase: E i h public void setService(MoneyTransferService service) { bli id tS i (M T fS i i) this.service = service; } Calls service @Override Verification: protected void onSetUp() throws Exception { super.onSetUp(); fromAccount = AccountMother Check state of .makeAccountWithNoOverdraft(FROM_ACCOUNT_INITIAL_BALANCE); toAccount = AccountMother database and .makeAccountWithNoOverdraft(TO_ACCOUNT_INITIAL_BALANCE); fromAccountId = fromAccount.getAccountId(); return values toAccountId = toAccount.getAccountId(); repository.addAccount(fromAccount); repository.addAccount(toAccount); repository addAccount(toAccount); Teardown: } public void testTransfer() { clean up service.transfer(fromAccountId, toAccountId, 5); assertBalance(FROM_ACCOUNT_INITIAL_BALANCE - 5, fromAccountId); (somehow) assertBalance(TO_ACCOUNT_INITIAL_BALANCE + 5, toAccountId); } 3/1/2009 17 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 18. The trouble with integration tests g Require lots of setup Setting up the database gp Initializing the database … 10x-100x slower than in-memory tests: y Use an in-memory database, e.g. HSQLDB Don’t commit transactions Database = persistence ⇒ test interference p Execute each test in a transaction that is rolled back ⇒ can interfere with session flushing/object loading Recreate the database schema ⇒ works well with HSQLDB Somehow write tests that only see data that they insert – can be tricky We still need integration tests but we can often g do better… 3/1/2009 18 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 19. Faster testing with mock objects g j A mock object simulates the real object: Returns values or throws exceptions th ti Verifies that the expected methods are called Using mocks: Simplifies tests Speeds up tests Enables an obje t to object be tested in isolation Enables top-down development 3/1/2009 19 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 20. Creating mocks g Write your own mocks Simple for interfaces but it becomes tedious. How t mock concrete classes? H to k tl ? Use a mock object framework jMOCK, EasyMock Create and configure mock object Specify expected method and arguments Define method behavior: return value or throw exception th ti 3/1/2009 20 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 21. Mock objects example: p j p part 1 import org.jmock…; public class MoneyTransferServiceTests extends MockObjectTestCase { protected void setUp() { super.setUp(); accountRepository = mock(AccountRepository class); mock(AccountRepository.class); bankingTransactionRepository = mock(BankingTransactionRepository.class); service = new MoneyTransferServiceImpl(accountRepository, bankingTransactionRepository); Create service with fromAccount = AccountMother.makeAccount(100); mock toAccount = AccountMother.makeAccount(200); fromAccountId = fromAccount getAccountId(); fromAccount.getAccountId(); repositories ii toAccountId = toAccount.getAccountId(); } 3/1/2009 21 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 22. Mock objects example: p j p part 2 p public class MoneyTransferServiceTests extends TestCase { y public void testTransfer_normal() throws Exception { checking(new Expectations() { { one(accountRepository).findAccount(fromAccountId); will(returnValue(fromAccount)); ill( l (f )) one(accountRepository).findAccount(toAccountId); will(returnValue(toAccount)); one(bankingTransactionRepository).addTransaction( with(is(BankingTransaction.class))); } }); BankingTransaction result = service .transfer(fromAccountId, toAccountId, 30); assertNotNull(result); MoneyUtil.assertMoneyEquals(70.0, fromAccount.getBalance()); MoneyUtil.assertMoneyEquals(230.0, toAccount.getBalance()); } 3/1/2009 22 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 23. Downsides of mocks Testing the collaboration of objects = white box testing Tests can be brittle Change design without changing what it does ⇒ failing tests Discourages ddevelopers f l from writing tests Fortunately, Fortunately many collaborations are stable e.g. e g between services and repositories 3/1/2009 23 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 24. Mock selectively! y Collaborators that slow tests down or introduce undesirable coupling: Repositories Remote Services Collaborators that require elaborate initialization, Stateful entities and value objects Collaborators that don't exist (yet) Entities when developing top down top-down Applications where message ordering is important 3/1/2009 24 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 25. Agenda g Introduction Testing services Testing entities and value objects g j Taming test fixture logic Simplifying verification code Writing more meaningful tests 3/1/2009 25 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 26. What's an Entity? y Objects with a public class Account { distinct identity private int id; Typically correspond private double balance; to real world private OverdraftPolicy overdraftPolicy; private String accountId; concepts private CalendarDate dateOpened; Almost always Account() { persistent } public void debit(double amount) throws MoneyTransferException { Encapsulate state and assert amount > 0; double originalBalance = balance; behavior double newBalance = balance - amount; overdraftPolicy.beforeDebitCheck(this, originalBalance, newBalance); balance = newBalance; Often modal ⇒ overdraftPolicy.afterDebitAction(this, originalBalance, newBalance); } testing is more public void credit(double amount) { difficult assert amount > 0; balance += amount; } 3/1/2009 26 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 27. What's a Value Object? j public class Account Objects that are defined private CalendarDate dateOpened; public class CalendarDate { by the values of their … p ate ate private Date date; } attributes CalendarDate() { Two instances with } identical values can be public CalendarDate(Date date) { this.date = date; used interchangeably } Two flavors public Date getDate() { return date; Persistent – parts of } entities public double getYearsOpen() { Calendar then = Calendar.getInstance(); Transient – intermediate then.setTime(date); values Calendar now = Calendar.getInstance(); Ideally immutable int yearsOpened = now.get(Calendar.YEAR) – then.get(Calendar.YEAR); Often missing from int monthsOpened = now.get(Calendar.MONTH) - then.get(Calendar.MONTH); procedural code d ld if (monthsOpened < 0) { ( th O d yearsOpened--; Have encapsulated state monthsOpened += 12; } and behavior return yearsOpened + (monthsOpened/12.0); } } 3/1/2009 27 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 28. Aggregates gg g A cluster of related entities and values Behaves as a unit Has a root Has b H a boundaryd Objects outside the aggregate can only reference the root Deleting the root removes everything Tests often create and test aggregates rather than individual objects 3/1/2009 28 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 29. Tests for entities and value objects j Fixture logic Create object under test (OUT) (often an aggregate) Create collaborators (also aggregates) Execution E ec tion Invoke method on OUT Verification Return value State of OUT State of collaborators Cleanup Usually do nothing – just use the g y gj garbage g collector 3/1/2009 29 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 30. Testing a POJO domain object g j p public class AccountTests extends TestCase { p public class Account { private Account account; private String accountId; private double balance; public void setUp() { private OverdraftPolicy account = new Account(quot;ABCquot;, 10.0, new overdraftPolicy; d ftP li NoOverdraftAllowed()); d f ll d()) } public double getBalance() { public void testInitialBalance() { return balance; MoneyUtil.assertMoneyEquals(10.0, } account.getBalance()); account getBalance()); } public void debit(double amount) public void testDebit() { {…} account.debit(6); MoneyUtil.assertMoneyEquals(4.0, public void credit(double account.getBalance()); amount) { … } } … Relatively easy to write tests } that run blindingly fast 3/1/2009 30 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 31. Mocking collaborators g Used less often - collaborators are usually fast to create But it can sometimes simplify tests Account and OverdraftPolicy Separate tests Account and OverdraftPolicies ⇒ Fewer, simpler tests But perhaps causes a feeling that you are not testing completely t t ti ltl Useful when creating a collaborator requires writing a l t of code i iti lot f d 3/1/2009 31 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 32. Agenda g Introduction Testing services Testing entities and value objects g j Taming test fixture logic Simplifying verification code Writing more meaningful tests 3/1/2009 32 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 33. What's a fixture Fixture = everything that needs to be in place to test an object Object we want to test Its collaborators Fixture is created by test fixture logic: Code in the test methods themselves Junit 3.x setUp() JUnit 4/TestNG @Before* annotations 3/1/2009 33 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 34. The challenge of test fixtures g Creating objects isn't always easy Individual objects have lots of parameters Objects are often belong to aggregates Test fixtures often create multiple T t fi t ft t lti l objects MoneyTransferServiceTests needs two accounts Multiple tests need the same set of objects AccountTests, MoneyTransferServiceTests need similar A i il Account objects t bj t 3/1/2009 34 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 35. Object g p j graphs can be complicated p We need all of these objects to test a Project! 3/1/2009 35 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 36. Constructing individual objects can be tricky y Best way to construct an object is to use a constructor: Supports objects without setters Supports immutable objects Forces you to support everything that's required Limitations of constructors: Lots of constructor arguments ⇒ code is difficult diffi l to read d Optional arguments ⇒ multiple constructors 3/1/2009 36 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 37. The alternative to constructors Project project = new Project(initialStatus); project.setName(quot;Test Project #1quot;); project.setDescription(quot;descriptionquot;); project.setRequirementsContactName(quot;Rick Jonesquot;); project.setRequirementsContactEmail(quot;jones@nowhere.comquot;); project.setType(ProjectType.EXTERNAL_DB); project.setArtifacts(new ArtifactType[] { ArtifactType.ARCHITECTURE, ArtifactType.DEPLOYMENT, ArtifactType.MAINTENANCE }); project.setInitiatedBy(user); •Handles optional parameters •Is more readable •But lots of noise: 'project set' project.set 3/1/2009 37 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 38. Constructing objects fluently g j y Project project = new Project(initialStatus) .name(quot;Test Project #1quot;) .description(quot;Excellent projectquot;) .initiatedBy(user) .requirementsContactName(quot;Rick Jonesquot;) .requirementsContactEmail(quot;jones@nowhere.comquot;) .type(ProjectType.EXTERNAL_DB) .artifact(ArtifactType.ARCHITECTURE) .artifact(ArtifactType.DEPLOYMENT) .artifact(ArtifactType.MAINTENANCE); • Chained method calls 3/1/2009 38 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 39. Pros and cons of this approach pp Benefits: Less noise Meaning of each value is clear Drawbacks: Breaks encapsulation – objects must have mutators/setters Doesn't work with immutable objects 3/1/2009 39 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 40. Fluently creating immutable objects y g j See http://developers.sun.com/learning/javaoneonl http://developers sun com/learning/javaoneonl ine/2007/pdf/TS-2689.pdf Project project = new Project.ProjectBuilder(initialStatus) .name(quot;Test Project #1quot;) (quot; j .description(quot;descriptionquot;) .initiatedBy(user) .requirementsContactName(quot;Rick Jonesquot;) .requirementsContactEmail(quot;jones@nowhere.comquot;) i C il(quot;j @ h quot;) .type(ProjectType.EXTERNAL_DB) .artifact(ArtifactType.ARCHITECTURE) .artifact(ArtifactType.DEPLOYMENT) .artifact(ArtifactType.MAINTENANCE) tif t(A tif tT MAINTENANCE) .make(); • Initialize the mutable builder • make() instantiates the domain object i obje t via a constructor on t to • Allows entity to be immutable 3/1/2009 40 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 41. Nested Entity Builder example y p class Project { public class ProjectBuilder { private String name; … public ProjectBuilder(Status initialStatus) { this.status = status; } ProjectBuilder name(String name) { this.name = name; return this; } public Project make() { // Verify that we have everything return new Project(this); } } • Pass builder as the sole public Project(ProjectBuilder builder) { constructor argument this.name = builder.name; this.initiatedBy = builder.initiatedBy; } 3/1/2009 41 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 42. Centralizing object creation with Object Mothers j Fluent interfaces can help but public class ProjectMother { Fixture logic can still be public static Project complex makeProjectInProposalState ( Status initialStatus, User user) { Same object created in … multiple t t ⇒ d li ti lti l tests duplication } Eliminate duplication: public static Project Centralize object creation in makeProjectInRequirementsState( Status initialStatus, User user) { a test utility class called an Object Mother … Defines factory methods for } creating fully formed aggregate } Different methods for different aggregate states See: http://www xpuniverse com/2001/pdfs/Testing03 pdf http://www.xpuniverse.com/2001/pdfs/Testing03.pdf 3/1/2009 42 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 43. Creating multiple connected aggregates gg g Each Object Mother method creates a single aggregate But B t some tests need tt d to create multiple aggregates with shared sub- h d b aggregates itDepartment = DepartmentMother.makeItDepartment(); Must avoid itProjectManager = duplicating that code UserMother.makeProjectManager(itDepartment); itBusinessAnalyst = UserMother.makeBusinessAnalyst(itDepartment); in multiple fixtures projectInCompleteState = ProjectMother.makeProjectInCompleteState(…); projectInRequirementsState = ProjectMother.makeProjectInRequirementsState(…); P j tM th k P j tI R i t St t ( ) … 3/1/2009 43 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 44. Use stateful object mothers j Test instantiates object mother Object mother's constructor Creates aggregates (by calling their Object Mothers) Stores them in (public) fields Test gets the data it needs from the object mother 3/1/2009 44 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 45. Example of a stateful mother public class ProjectTests extends TestCase { private Project project; private User projectManager; private User businessAnalyst; public class PTrackWorld { protected void setUp() throws Exception { private final Department itDepartment; PTrackWorld world = new PTrackWorld(); private fi l User itP j tM i t final U itProjectManager; projectManager = world.getItProjectManager(); private final Project projectInCompleteState; businessAnalyst = world.getItBusinessAnalyst(); project = world.getProjectInProposalState(); } … public PTrackWorld() { itDepartment = DepartmentMother.makeItDepartment()' itProjectManager = UserMother.makeProjectManager(itDepartment); stateMachine = DefaultStateMachineFactory.makeStateMachine(quot;defaultquot;); initialStatus = stateMachine.getInitialStatus(); projectInCompleteState = ProjectMother.makeProjectInCompleteState(initialStatus, itProjectManager, getAllITDepartmentEmployees()); … } } 3/1/2009 45 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 46. Object Mother design j g Choices Same data each time vs. random data Referenced aggregates as parameters vs. create those aggregates too Tip: use descriptive names Bad: makeProject1(), makeProject2(), ... Better: makeProjectIn<State>(), … Tip: use Object Mothers from day 1 But don’t create obscure tests Hiding details in mothers can make tests difficult to understand ShoppingCartMother.makeWithInstockPartBackorderedPartandDiscontinuedPart() ?!? Need to find the balance between too much and too little 3/1/2009 46 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 47. Agenda g Introduction Testing services Testing entities and value objects g j Taming test fixture logic Simplifying verification code Writing more meaningful tests 3/1/2009 47 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 48. Writing readable verification logic Verification phase verifies that expected outcome has been obtained State verification makes assertions about: Returned value State of object under test State of collaborators Test frameworks provide the basic assert methods but we must: Ensure readability Avoid code duplication 3/1/2009 48 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 49. Using Custom Assertions Verifying the state of object multiple assert…() calls = obscure code In multiple tests = code duplication Verification code calls a Test Utility Method that makes assertions Has an Intention Revealing Name Benefits: Makes the code more readable Eliminates duplication p 3/1/2009 49 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 50. Example – before and after protected void setUp() throws Exception { PTrackWorld world = new PTrackWorld(); projectManager = world.getItProjectManager(); project = world.getProjectInProposalState(); protected void setUp() throws Exception { startTime = new Date(); … expectedOperation0 = state0 = world.getInitialState(); new Operation(null, projectManager, state1 = state0.getApprovalStatus(); state0, state1, state2 = state1.getApprovalStatus(); g pp (); quot;Excellentquot;); quot; ll quot;) } } public void testChangeStatus() throws InterruptedException { public void testChangeStatus() boolean result = project.changeStatus(true, { projectManager, quot;Excellentquot;); boolean result = project.changeStatus(true, Date endTime = new Date(); projectManager, quot;E j tM quot;Excellentquot;); ll tquot;) Date endTime = new Date(); assertTrue(result); assertEquals(state1, project.getStatus()); assertTrue(result); assertEquals(1, project.getHistory().size()); assertEquals(state1, project.getStatus()); Operation operation = project.getHistory().get(0); assertHistoryContains(project, assertHistoryContains(project assertEquals(quot;Excellentquot;, operation.getComments()); l (quot; ll quot; i C ()) startTime, endTime, assertEquals(projectManager, operation.getUser()); expectedOperation0); assertEquals(state0, operation.getFromStatus()); } assertEquals(state1, operation.getToStatus()); assertFalse(operation.getTimestamp().before(startTime)); assertFalse(operation.getTimestamp().after(endTime)); } 3/1/2009 50 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 51. Example - After private void assertHistoryContains(Project project, Date startTime, Date endTime, Operation... expectedOperations) { int i = 0; List<Operation> history = project.getHistory(); assertEquals(expectedOperations.length, history.size()); for (Operation expectedOperation : expectedOperations) { Operation operation = history.get(i++); assertOperationEqual(expectedOperation, startTime, endTime, assertOperationEqual(expectedOperation startTime endTime operation); startTime = operation.getTimestamp(); } } private void assertOperationEqual(Operation expectedOperation, Date startTime, Date endTime, Operation operation) { assertEquals(expectedOperation.getComments(), operation.getComments()); assertEquals(expectedOperation.getUser(), operation.getUser()); assertEquals(expectedOperation.getFromStatus(), operation.getFromStatus()); assertEquals(expectedOperation getFromStatus() operation getFromStatus()); assertEquals(expectedOperation.getToStatus(), operation.getToStatus()); assertFalse(operation.getTimestamp().before(startTime)); assertFalse(operation.getTimestamp().after(endTime)); } 3/1/2009 51 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 52. Literate assertions with Hamcrest Hamcrest is an open-source framework http://code.google.com/p/hamcrest/ Readable quot;literatequot; assertions Rich set of composable matchers Literate error messages Used by Jmock expectations import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; org hamcrest Matchers is; import static org.hamcrest.Matchers.isOneOf; assertThat(project.getStatus(), is(state1)); assertThat(project.getStatus(), isOneOf(state1, state2)); assertThat(project.getStatus(), allOf(is(state), not(is(state2)))); tTh t( jt tSt t () llOf(i ( t t ) t(i ( t t 2)))) 3/1/2009 52 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 53. Hamcrest custom matchers public class ProjectMatchers { p public static Matcher<Date> withinInclusivePeriod(final Date startTime, ( , final Date endTime) { return new TypeSafeMatcher<Date>() { public boolean matchesSafely(Date date) { return !date.before(startTime) && !date.after(endTime); } public void describeTo(Description description) { description.appendText(String.format(quot;expected to be between <%s> and <%s>quot;, startTime, endTime)); } import static org.jia.ptrack.domain.ProjectMatchers.withinInclusivePeriod; p gj p j ; }; } public void testChangeStatus() { assertThat(operation.getTimestamp(), is(withinInclusivePeriod(startTime, endTime))); } java.lang.AssertionError: Expected: is expected to be between <Wed Nov 14 19:39:23 PST 2007> and <Wed Nov 14 19:39:23 PST 2007> got: <Wed Dec 31 16:00:00 PST 1969> at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:21) g ( j ) 3/1/2009 53 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 54. Agenda g Introduction Testing services Testing entities and value objects g j Taming test fixture logic Simplifying verification code Writing more meaningful tests 3/1/2009 54 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 55. TDD says begin with a test but… Daddy, where do tests come from? 3/1/2009 55 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 56. Best to derive tests from requirements q As a customer of the bank I want to transfer money between two bank accounts So that I don't have to write a check class AccountTransferServiceTests … { public void testTransfer_ok() { Account savingsAccount = AccountMother.makeAccountWithNoOverdraft(150); Account checkingAccount = Given that my savings account balance is $150 AccountMother.makeAccountWithNoOverdraft(10); Given that my checking account balance is $10 String savingsAccountId = savingsAccount.getAccountId(); When I transfer $50 from my savings account String checkingAccountId = checkingAccount.getAccountId(); to my checking account repository.addAccount(savingsAccount); Then my savings account balance is $100 repository.addAccount(checkingAccount); p y ( g ); Then my checking account balance is $60 service.transfer(savingsAccountId, checkingAccountId, 50); assertBalance(100, savingsAccountId); assertBalance(60, checkingAccountId); } Given that my savings account balance is $150 Given that my checking account balance is $10 public void testTransfer_overdraftAttempted() { Given that my bank does not allow me …. to have an overdraft } When I transfer $200 from my savings account to my checking account y g Then my savings account balance is unchanged Then my checking account balance is unchanged 3/1/2009 56 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 57. Testing at multiple levels g p Where in the hierarchy to write a test? Web tier Service integration test Mock service test Entity/Value object test Sometimes at every level Few high-level tests, e g verify that the UI tests e.g. handles errors Many lower-level, more detailed tests, e.g. tests for each error scenario Sometimes only lower-level tests E.g. verifying that email is sent after transferring money ⇒ mock object service test fi k bj i 3/1/2009 57 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 58. We sometimes invent requirements q User requirements focus on the external behavior: Behavior of boundary classes, i.e. UI + services Key domain model classes, e.g. account But those classes often have collaborators: E.g. Account has CalendarDate When designing those classes: Informally specify the behavior of those classes Write capture that behavior in tests 3/1/2009 58 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 59. More formal testing g 1000+ pages of rigorous testing techniques 3/1/2009 59 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 60. Deriving tests from a state machine model • State machine is a useful way to model some classes (and ( r UIs) • N+ test strategy • Turn state machine into a p q A B C tree containing all edges • Test cases = paths to all leaves s •Test = sequence of events public testPQR() { } public testPS() { } 3/1/2009 60 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 61. Deriving tests from boolean expressions p Class invariant/function/conditional: (x >= 1 & y < 10) Variable Condition Test #1 #2 #3 #4 x X >= 1 > On 1 Off 0 Typical 10 10 Y Y < 10 On 10 Off 9 Typical 2 2 Result True False False True 1x1 selection criteria 3/1/2009 61 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 62. Derive tests from code Write tests to improve code coverageg Identifies behavior/edge cases that you forgot to test Characterization tests: Capture current behavior Useful for refactoring (sometimes) But they can be brittle Tip: Use a code coverage Code might not be tool: Cobertura (f t l Cb t (free), ) correct! Clover (cheap), … 3/1/2009 62 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 63. Use code metrics to identify what to test Cyclomatic complexity Bugs lurk here Simplify if you can Large methods L th d Bugs lurk in here also Simplify if you can Crap4J (www.crap4j.org) Computes code quality by combining code coverage and complexity 3/1/2009 63 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 64. Summary y Testing is essential Use mock objects to accelerate tests Aggressively refactor tests to keep gg y p them simple Use Object Mothers to avoid j duplication of test fixture logic Simplify assertions Derive tests from requirements 3/1/2009 64 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 65. For more information Buy my book ☺ Go to manning.com Send email: chris@chrisrichardson.net Visit my website: http://www.chrisrichardson. net Talk to me about consulting and training 3/1/2009 65 Copyright (c) 2007 Chris Richardson. All rights reserved.