本測(cè)試處理[Test]屬性,還有一個(gè)[ExpectedException ]屬性與之關(guān)聯(lián)-這是一種用來(lái)描述測(cè)試代碼期望某種特定異常的方式。如果這種異常在執(zhí)行的過(guò)程中沒(méi)有拋出-測(cè)試失敗。編譯你的代碼并返回到GUI。在你編譯測(cè)試代碼的同時(shí),GUI變灰,并且收緊測(cè)試樹(shù),因?yàn)闇y(cè)試還沒(méi)有運(yùn)行(當(dāng)測(cè)試樹(shù)結(jié)構(gòu)改變時(shí),GUI會(huì)觀察測(cè)試的程序集的改變,并更新它自己-例如,加入新的測(cè)試等)。點(diǎn)擊“Run”按鈕-我們又有一個(gè)紅色的狀態(tài)條。我們會(huì)得到如下失。
TransferWithInsufficentFunds : InsufficientFundsException was expected
讓我們?cè)僖淮涡迯?fù)Account代碼,按如下方法修改TransferFunds:
public void TransferFunds(Account destination, float amount)
{
destination.Deposit(amount);
if(balance-amount<minimumBalance)
throw new InsufficientFundsException();
Withdraw(amount);
}
編譯并運(yùn)行測(cè)試-綠色的狀態(tài)條。成功了!但是等等,看看我們剛才編寫(xiě)的代碼,我們會(huì)發(fā)現(xiàn)銀行可能在每個(gè)沒(méi)有成功的轉(zhuǎn)帳操作失去一筆錢。讓我們編寫(xiě)一個(gè)測(cè)試來(lái)證明我們的疑慮,增加如下測(cè)試方法:
[Test]
public void TransferWithInsufficientFundsAtomicity()
{
Account source = new Account();
source.Deposit(200.00F);
Account destination = new Account();
destination.Deposit(150.00F);
try
{
source.TransferFunds(destination, 300.00F);
}
catch(InsufficientFundsException expected)
{
}
Assert.AreEqual(200.00F,source.Balance);
Assert.AreEqual(150.00F,destination.Balance);
}
我們正測(cè)試業(yè)務(wù)方法的事務(wù)屬性-要么都成功,要么都失敗。編譯并運(yùn)行-紅條。OK,我們已經(jīng)讓$300.00蒸發(fā)了((1999.com déjà vu?)-源帳戶有一個(gè)正確余額150.00,但是目標(biāo)帳戶則是$450.00.我們?nèi)绾涡迯?fù)?我們僅需要將小余額檢查調(diào)用放在更新的前面即可:
public void TransferFunds(Account destination, float amount)
{
if(balance-amount<minimumBalance)
throw new InsufficientFundsException();
destination.Deposit(amount);
Withdraw(amount);
}
如果Withdraw()方法拋出另外一個(gè)異常怎么辦?我們應(yīng)該在捕獲代碼段中執(zhí)行一個(gè)追加的業(yè)務(wù),或是依賴我們的事務(wù)管理器來(lái)恢復(fù)對(duì)象的狀態(tài)?關(guān)于這點(diǎn),我們需要回答一些問(wèn)題,但不是現(xiàn)在。同時(shí),我們應(yīng)該對(duì)失敗的測(cè)試些什么呢?刪除它?一個(gè)比較好的方式是暫時(shí)忽略它,在測(cè)試代碼中加入如下屬性:
[Test]
[Ignore("Decide how to implement transaction management")]
public void TransferWithInsufficientFundsAtomicity()
{
// code is the same
}
編譯并運(yùn)行-黃色的狀態(tài)條。點(diǎn)擊“Tests Not Run”,在列表里你會(huì)看到e bank.AccountTest.TransferWithInsufficientFundsAtomicity() ,而且?guī)в袦y(cè)試忽略的原因:
看一下我們的測(cè)試代碼,我們會(huì)發(fā)現(xiàn)某些重構(gòu)是有順序的。所有測(cè)試方法都共享一組通用的測(cè)試對(duì)象。我們將這個(gè)初始化代碼提取到一個(gè)setup方法里,并在所有測(cè)試中重用它。我們測(cè)試類的重構(gòu)版本如下: