0

我正在为我的客户端/服务器设置构建一个 TestProject。我想验证测试是否在某个执行块内失败(没有要发送的客户端,因此服务器的 Send() 方法将引发异常)。因为我不想让测试启动客户端和服务器并让它们通信(我在单台机器上遇到了问题。)

如果代码到达这一行,这意味着程序的执行流程只能在另一个测试的职责范围内失败。除了对抛出的异常的堆栈跟踪进行子字符串检查之外,还有更简单的方法吗?我觉得这种方法的可扩展性不是很好,如果类名发生变化,需要不断关注。

有没有一种方法甚至不涉及手动检查异常的堆栈跟踪?

4

3 回答 3

2

如果您使用的是 NUnit

不使用 DataAnnotations

[Test]
public void Test_XXXXXXX
{
    var yourClass = new YourClass(); 
    Assert.That(()=>yourClass.Method(),
                    .Throws.Exception
                    .TypeOf<TypeOfYourException>
                    .With.Property("Message")
                    .EqualTo("the message you are expecting goes here")
               );
}

使用数据注解

[Test]
[ExpectedException(typeof(ExceptionType), ExpectedMessage="your message goes here!")]
public void Test_XXXXXXX
{
      var yourClass = new YourClass();     
      // Call your method in a way that it will fail
      yourClass.YourMethod();
}
于 2013-07-21T22:35:24.807 回答
0

当您对某个类进行单元测试时,有两个异常来源:

  1. 您正在测试的类可能会引发异常
  2. 类的依赖可以抛出异常

在第二种情况下,您通常要么处理异常,要么将其包装在更高级的异常中并将其抛出给调用者。那么,如何测试所有这些情况呢?

被测系统抛出异常

例如,在传递给方法的参数错误的情况下抛出异常(NUnit 示例):

StockService service = new StockService();
Assert.Throws<ArgumentNullException>(() => service.Connect(null));

您不需要检查堆栈跟踪,因为它是一个被测试的类,应该抛出异常。

依赖抛出异常,我们处理它

当您的类具有依赖项时,您应该模拟依赖项以便单独测试您的类。因此,设置模拟以在您的类与它们交互时抛出异常非常容易。如果未找到配置文件(最小起订量示例),请考虑服务应在默认设置下运行的情况:

var configMock = new Mock<IStockServiceConfig>();
configMock.Setup(c => c.Load()).Throws<FileNotFoundException>();

StockService service = new StockService(configMock.Object);
service.Connect("google");

configMock.VerifyAll();
Assert.That(service.Port, Is.EqualTo(80));

如果您不尝试加载配置,或者如果您不处理FileNotFoundException.

异常堆栈跟踪在这里无关紧要 - 我们不关心我们的直接依赖项是否抛出异常,或者它是依赖项中的其他一些类。实际上我们不知道那个类是否存在——我们只与直接依赖进行交互。我们应该只关心依赖可以抛出我们可以处理的异常这一事实。

依赖抛出异常,我们包装它

最后一种情况 - 将异常包装在更高级的东西中。考虑前面的示例,但配置非常重要,没有配置文件就无法启动。在这种情况下,您将包装FileNotFoundException到更特定于业务的东西中,这在应用程序的更高级别是有意义的。例如StockServiceInitializationException

var configMock = new Mock<IStockServiceConfig>();
configMock.Setup(c => c.Load()).Throws<FileNotFoundException>();

StockService service = new StockService(configMock.Object);
Assert.Throws<StockServiceInitializationException>(_ => service.Connect("bing"));

configMock.VerifyAll();

如您所见,我们也不关心异常的堆栈跟踪,这会引发我们的依赖。它也可能是更底层异常的一些包装器。服务的预期行为 - 如果找不到配置,则抛出高级初始化异常。我们正在这里验证这种行为。

于 2013-07-21T23:11:34.630 回答
0

除了特定于该类之外,该类中的异常是否有任何独特之处?

如果可以通过消息识别它,则可以按照其他答案所示对其进行测试,或者如果您不使用 NUnit,则像这样:

try {    
   myMethod();
   Assert.Fail("Expected exception to be thrown."); 

} catch (MyException ex) {    
   Assert.Equals("My Exception Message", ex.Message, "Exception message was formatted incorrectly.");

} catch (Exception) {    
   Assert.Fail("An exception was thrown, but of the wrong type.");    
}
于 2013-07-21T22:50:52.177 回答