title: Unit-testing Service bean which uses Spring+JPA but no DB is available
body: <p>A simple banking application:
  <img src="https://i.stack.imgur.com/gD189.png" alt="enter image description here"></p>
  
  <p>Points to note:</p>
  
  <ul>
  <li>Using Spring+JPA with EclipseLink as JPA provider</li>
  <li>EntityManager is injected into BaseDaoImpl using @PersistenceContext</li>
  <li>DAOs are autowired into the Service bean</li>
  <li>@Transactional annotation used at service methods</li>
  </ul>
  
  <p>Objective: Unit-test Service methods as part of maven build</p>
  
  <p>Unit-test = simple API testing. For example, a service method: <code>transfer(int fromAccountId, int toAccountId, double amount)</code> has unit-test cases:</p>
  
  <ul>
  <li><code>fromAccountId</code> should not be 0</li>
  <li><code>toAccountId</code> should not be 0</li>
  <li><code>fromAccountId</code> != <code>toAccountId</code></li>
  <li>`amount is greater than 0</li>
  <li>etc.</li>
  </ul>
  
  <p>These "unit-test" cases do not require DB connection.</p>
  
  <p>Problem: Build server has no DB setup. However, when the unit-test case is executed, Spring tries to connect to DB which fails. However, we do not really need DB connection for these cases to go through. (We have another set of "integration cases" - these are not executed as part of the normal build but will be executed manually with full environment available. How? - See <a href="https://stackoverflow.com/questions/22940571/junit-selectively-not-run-a-few-test-cases-as-default">this thread</a>)</p>
  
  <p>Questions:</p>
  
  <ul>
  <li>What are the best practices to execute these kinds of unit test cases?</li>
  <li>Can we force Spring not to make DB connection till the last minute it is actually needed? (Right now, it does when it encounters <code>@Transactional</code> method)</li>
  </ul>
  
  <hr>
  
  <p>Adding Service Layer code as requested:</p>
  
  <pre><code>public class BankManagerImpl implements BankManager {
  
      @Autowired
      AccountDao accountDao;
  
      @Autowired
      TransactionDao transactionDao;
  
      ...
  
      @Override
      @Transactional
      public void deposit(int accountId, double amount) {
          Account a = accountDao.getAccount(accountId);
          double bal = a.getAmount();
          bal = bal + amount;
          a.setAmount(bal);
  
          accountDao.updateAccount(a);
  
          transactionDao.addTransaction(a, TransactionDao.DEPOSIT, amount);
      }
  
      @Override
      @Transactional
      public void withdraw(int accountId, double amount) {
          Account a = accountDao.getAccount(accountId);
  
          double bal = a.getAmount();
          if(bal &lt; amount) {
              throw new RuntimeException("insufficient balance");
          }
  
          bal = bal - amount;
          a.setAmount(bal);
  
          accountDao.updateAccount(a);
  
          transactionDao.addTransaction(a, TransactionDao.WITHDRAW, amount);
      }
  
      @Override
      @Transactional
      public void transfer(int fromAccountId, int toAccountId, double amount) {
          withdraw(fromAccountId, amount);
          deposit(toAccountId, amount);
      }
  
      ...    
  
  }
  </code></pre>