0

编辑:为了我自己的理智更新了 21/09/12……我不敢相信这曾经是一个问题(是的学习)。

控制台元素让我有点远离这个气味。如果我只是想检查错误,而不是特别是消息,那么只是断言(期望)异常可能会起作用。记录控制台活动并检查日志会起作用。帖子末尾详细介绍的系统响应想法会奏效。这种事情有很多选择。吨!我的结论?做任何最有意义/最不脆弱的事情。只要您的场景是可靠的并且您正在证明行为,这一切都很好。


我的 BDD 任务继续使用 .NET 中的一个简单的控制台应用程序(VS2010、SpecFlow 和 NUnit)。

对于这样的场景,我遇到了障碍:

Feature: Withdraw Money
Scenario: Insufficient Funds
Given I have a MoneyBox
And my MoneyBox contains £10
When I withdraw £20
Then the system should display an error message
And my MoneyBox should contain £10

定义上下文很好,尝试提取资金很好。所有相关的单元测试都很好。最后保持平衡很好。

我想像这样实现一些 .Withdraw() 方法:

//Assume the moneybox only contains £1 coins (hence int is ok)
public void Withdraw(int withdrawlAmount) throws InsufficientFundsException
{
if(this.balance >= withdrawlAmount)
{
this.balance -= withdrawlAmount;
}
else
{
throw new InsufficientFundsException();
}
}

我可以对该代码进行单元测试(通过通过和失败条件测试)。

但是,在控制台应用程序的上下文中,我不太清楚如何断言:

Then the system should display an error message

任何想法、提示或参考将不胜感激。

编辑1:

请注意,我的问题仅涉及通过使用 BDD 方法的验收测试来证明错误消息。感觉是语境问题。再次感谢。

编辑2:

一种方法可能是重新考虑场景,或者更确切地说是它的实现。MoneyBox 代码可以按原样编写(经过单元测试,未经验收测试的纯 BO),但它的功能可以包装在某个上下文类中:

超级快速示例:

public class MoneyBoxDriver
{
private MoneyBox objMB
private SystemResponse objSR

//Standard stuff e.g. constructor

private void Withdraw(int withdrawAmount)
{
try
{
objMB.Withdraw(withdrawAmount);
}
catch(InsufficientFundsException)
{
this.objSR = new SystemResponse(SystemResponseEnum.FailedInsufficientFunds);
}
}

然后我们可以将 MoneyBoxDriver 设置为上下文,通过 Withdraw 包装器方法对其进行操作,然后通过检查 MoneyBoxDriver 的 SystemResponse 来断言功能。

Then the system should display an insufficient funds error message
...
Assert.That(MBDriver.SystemResponse.Type == SystemResponseEnum.FailedInsufficientFunds)
...

如果 SystemResponse 属于给定类型,则在 UI(控制台)中可能有显示错误消息的简单代码。

4

1 回答 1

2

这是任何类型的测试优先方法的乐趣的一部分,它将迫使您以可以测试的方式设计您的对象 - 而且他们会因此而变得更好!

在此示例中,我将考虑执行以下操作:(请注意,以下代码尚未经过测试,也不是“完美”解决方案 - 但它更易于测试并且更接近您想要的位置)。

//Assume the moneybox only contains £1 coins (hence int is ok)
public void Withdraw(int withdrawlAmount, Action<InsufficientFundsException> handleException)
{
     if(this.balance >= withdrawlAmount)
     {
          this.balance -= withdrawlAmount;
     }
     else
     {
          handleException(new InsufficientFundsException());
     }
}

然后,您可以在测试代码中为可能的异常设置一个字段或属性,当您调用 Withdraw 方法时,只需指定一个快速操作来执行回调,例如:

moneyBox.Withdraw(10, e => this.WithdrawException = e);

然后,您的Then语句可以断言 theWithdrawException不为空,并对其中的消息进行断言。

您的生产代码(即控制台应用程序)可能会这样做:

moneyBox.Withdraw(10, e => Console.WriteLine("Error: {0}", e.Message));

更完美的解决方案是将 替换为 或类似的Action<InsufficientFundsException>东西Action<MoneyBoxWithdrawResponse>。其中MoneyBoxWithdrawResponse包含有关操作成功的信息,可能还有余额以及任何潜在的错误/异常详细信息。

于 2012-08-14T14:40:10.157 回答