Print
Category: IT
Hits: 653

Test behavior, not method

When code is difficult to test, most like the design needs to be improved

Break up an object when it becomes too large to test easily, or failures too difficult to interpret

Keep interfaces narrow

Keep all dependencies (e.g. time) to application external so they can be provided at test time

Do not mock immutable values

Separate functional concern with multithreading concern, use DeterministicExecutor for thread testing.
 

Encapsulate functions such as logging:

support.notifyfiltering(....., filter)

 

Never pass null between objects, instead use:

final Foo::NULL = null;

 

Bloated constructor might mean object has too many responsibilities

A constructor that has too many non-final parameters can be rewritten such that only the final parameter is set and other dependencies are set in the declaration.

For example:

  class Foo {

    final Bar arg1;
    Bar arg2 = Bar.createInstance();
    Bar arg3 = Bar.createInstance();

     foo(Bar arg1) {
       this.arg1 = arg1;
     }
     arg2(Bar arg2) {
       this.arg2 = arg2;
     }
   .....

  }

For simpler object creation, use builder pattern

  class Builder {
    static Builder newObject();    // returns a defaut object
    Builder withArg1();
    Builder withArg2();
    Obj build();
  }

 

Setup transaction using common pattern

  public class JPATransactor {
    private final EntityManager entityManager;
    public JPATransactor(EntityManager entityManager) {
      this.entityManager = entityManager;
    }
    public void perform(UnitOfWork unitOfWork) throws Exception {
      EntityTransaction transaction = entityManager.getTransaction();
      transaction.begin();
      try {
        unitOfWork.work();
        transaction.commit();
      }
      catch (PersistenceException e) {
        throw e;
      }
      catch (Exception e) {
        transaction.rollback();
        throw e;
      }
    }
}