[英]Unit-testing Service bean which uses Spring+JPA but no DB is available
一個簡單的銀行應用程序:
注意事項:
目標:作為Maven構建的一部分的單元測試服務方法
單元測試=簡單的API測試。 例如,服務方法: transfer(int fromAccountId, int toAccountId, double amount)
具有單元測試用例:
fromAccountId
不應為0 toAccountId
不應為0 fromAccountId
!= toAccountId
這些“單元測試”情況不需要DB連接。
問題:構建服務器沒有數據庫設置。 但是,當執行單元測試用例時,Spring嘗試連接到失敗的DB。 但是,對於這些情況,我們確實不需要數據庫連接。 (我們還有另一套“集成案例”-這些不是作為常規構建的一部分執行的,而是在可用的完整環境下手動執行的。如何?-請參見此線程 )
問題:
@Transactional
方法時會執行此操作) 根據要求添加服務層代碼:
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 < 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);
}
...
}
您需要的是集成測試。 首先,您必須構建一個虛擬的 PlatformManager
並確保將其用於測試。 您將在SO上的另一篇文章中找到有關此方面的線索。 我如何在JUnit測試中模擬TransactionManager(在容器外部)? 以及下面的另一個(部分)示例。
當spring按順序應用ApplicationContext
定義時(最后一個覆蓋其他),您只需在最后一個位置添加一個XML(或JavaConfig)文件測試,以聲明虛擬PlatformManager
具有與常規配置中相同的bean名稱。
然后,您從應用程序上下文中獲取服務bean,並用模擬(Mockito或您喜歡的東西)替換其Dao。
根據您要測試的內容,您必須調整虛擬的PlatformManager
,但是如果您簡單地添加:
public class MockedTransactionManager implements PlatformTransactionManager {
public boolean transactionStarted = false
public commited = false;
public rollbacked = false;
@Override
public TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
transactionStarted = true;
return null;
}
@Override
public void commit(TransactionStatus status) throws TransactionException {
commited = true;
}
@Override
public void rollback(TransactionStatus status) throws TransactionException {
commited = true;
}
您將能夠控制是開始,提交還是回滾事務。 如果有特殊要求,則可能必須創建一個真實的SimpleTransactionStatus
而不是傳遞null。
目的是在單元測試期間禁用數據庫連接。 一種方法是@Serge Ballesta的答案中提到的模擬交易經理。 我們發現了一種更簡單的方法-在單元測試期間,我們完全禁用了加載事務管理器。 這可以通過在應用程序上下文中注釋掉下面的行來完成,這可以防止基於注釋的事務被啟動。
<!-- <tx:annotation-driven transaction-manager="transactionManager" /> -->
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.