点击“Run”按钮——我们又一次得到了一个红色的状态条。我们得到了下面的失败消息:“TransferWithInsufficentFunds: InsufficientFundsException was expected”。我们来再次修改Account的代码,象下面这样修改TransferFunds()方法:
public void TransferFunds(Account destination, float amount) { destination.Deposit(amount); if(balance - amount < minimumBalance) throw new InsufficientFundsException(); Withdraw(amount); }
编译并运行测试——绿了。成功!不过等等,看看我们刚写的代码,我们会发现银行在每一笔不成功的转账操作时都亏钱了。让我们来写一个测试来确认我们的猜测。添加这个测试方法:
[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); }
我们测试了方法的交易属性——是否所有的操作都成功了。编译并运行——红条。是的,我们平白无故地损失了300块钱——source账户有正确的余额150.00,但destination账户显示:$450.00。我们该如何修改?我们能够只将最小余额检查的调用放到数据更新的前面么:
public void TransferFunds(Account destination, float amount) { if(balance - amount < minimumBalance) { throw new InsufficientFundsException(); } destination.Deposit(amount); Withdraw(amount); }
如果Withdraw()方法抛出了另外一个异常呢?我们应该在catch块中执行一个补救处理,还是依赖我们的交易管理器来重新装载对象的状态?某些时候我们必须回答这样的问题,但不是现在;可我们眼前如何应付这个失败的测试呢——删除它?一个不错的方法是临时忽略它在你的测试方法中添加下面的特性:
[Test] [Ignore("Need to decide how to implement transaction management in the application")] public void TransferWithInsufficientFundsAtomicity() { // code is the same }
编译并运行——黄条。单击“Test Not Run”选项卡,你会看到bank.AccountTest.TransferWithInsufficientFundsAtomicity()连同这个测试被忽略的原因一起列在列表中。