10

对 WCF 服务的预期故障进行单元测试的最佳方法是什么?

我正在尝试对 WCF 服务进行单元测试,该服务(正确地)为某个可重现的错误抛出 FaultExceptions。单元测试获取 WCF 客户端的实例并调用适用的服务方法,这会引发 FaultException。

所有这些都可以按您的预期工作,但是我很难对此进行单元测试,因为当错误未在服务实现中捕获时,错误会导致 IDE 中断。因为我使用的是错误而不是异常,所以我希望 IDE 序列化异常并将其发送到客户端,在那里它会引发异常。

我确实看到有一个配置选项可以为特定的用户未处理的异常禁用中断,但我希望有人能指出一种更好的方法来实现相同的结果,因为这在团队环境中并不容易实现。

这是当前实现的一些示例代码...

单元测试项目有一个对我的 WCF 服务的服务引用,我已经将接口定义为:

[OperationContract(Name = "DoSomething")]
[FaultContract(typeof(EpicFail))]
ResponseObject DoSomething(RequestObject requestObject);

故障定义如下:

[DataContract]
public class EpicFail
{

    public EpicFail(string action)
    {
        this.Reason = "Epic Fail";
        this.Action = action;
    }

    [DataMember]
    public string Reason
    {
        get;
        set;
    }

    [DataMember]
    public string Action
    {
        get;
        set;
    }

}

调用服务的代码大致如下:

[TestMethod()]
[ExpectedException(typeof(FaultException<EpicFail>))]
public void FaultTest_Fails_Epicly()
{
    bool testPassed = false;

    try
    {
        ResponseObject resp = GetServiceClient().DoSomething(req);
    }
    catch (FaultException<EpicFail>)
    {
        testPassed = true;
    }

    Assert.IsTrue(testPassed);
}
  • 我编辑了代码以显示我正在使用 ExpectedException 属性,并且当服务中引发异常时,它似乎对保持 IDE/调试器不会中断有太大影响。
4

2 回答 2

1

您始终可以使用ExpectedExceptionAttribute(在 NUnit 中)来确保这是引发的异常。MSTest 也有类似的概念。

[ExpectedException(typeof(MyException))]
void my_test()
{
     // test
}

如果你有一些 Mock 验证要做,我会使用 try/catch 块并在 catch 中验证,然后抛出异常。

更新

当您使用ExpectedException属性时,您不应该捕获异常,而是需要让运行测试的 NUnit 捕获它。

如果您需要验证异常中的特殊信息,则捕获异常,验证信息然后重新抛出:

[ExpectedException(typeof(MyException))]
void my_test()
{
     try
     {
         // call the service
     }
     catch(MyException ex)
     {
          Assert.IsTrue(ex.Message.Contains("error code 200"));
          throw ex;
     }

}
于 2010-11-01T17:16:03.497 回答
1

马特电视,

为什么这个测试必须远程访问服务?从我看到你的代码:

ResponseObject resp = GetServiceClient().DoSomething(req);

以某种方式获取服务客户端,而不是服务实例本身。我建议直接测试服务具体类以进行单元测试。

但是,如果您需要这种情况,您是否尝试过不捕获异常并运行测试?它给出相同的结果吗?

顺便说一句,如果您需要捕获并重新抛出,请使用以下模式:

try {
   //Do something
}
catch(SomeException e) {
   //Do something with e
   throw
}
于 2011-04-01T07:21:01.203 回答