2010-11-01 145 views
9

从WCF服务单元测试预期故障的最佳方式是什么?单元测试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 /调试太大的影响。
+0

你在同一个进程中的单元测试托管WCF服务,或在单独的进程? – 2010-11-02 07:06:19

+0

单独的进程,WCF服务通过IIS托管。我在调试模式下本地运行单元测试。这两个项目都是同一解决方案的一部分。我认为如果我在构建模式下运行服务,并在调试模式下运行单元测试,它可能会解决这个问题,但这似乎不是一个更好的解决方案,然后是IDE配置选项。这仍然是我必须为每个人机。 – mattv 2010-11-02 13:22:52

+0

您是否配置了IDE以打破所有异常? – Kristen 2010-11-25 22:52:52

回答

1

您可以随时使用ExpectedExceptionAttribute(在NUnit中)确保这是抛出的异常。 MSTest也有类似的概念。

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

如果你有一些模拟验证的事,我会用try/catch块,并在catch验证,然后抛出异常。

UPDATE

当您使用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; 
    } 

} 
+0

我实际上是在单元测试中使用ExpectedException属性。也许我错误地使用了它。我将在示例代码中追加我正在做的事情。 – mattv 2010-11-01 19:16:24

+0

查看我的更新。 – Aliostad 2010-11-01 22:47:16

+0

呃,谢谢你告诉我这个属性的正确用法 - 遗憾的是,仍然没有解决我的问题。尽管现在当我恢复应用程序之后,测试通过了,但异常中断了! – mattv 2010-11-02 13:20:55

1

mattv,

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

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

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

但是,如果你需要这种情况下,你有没有试过不捕捉异常并运行测试?它是否给出相同的结果?

顺便说一下,如果你需要赶上并重新抛出使用以下模式:

try { 
    //Do something 
} 
catch(SomeException e) { 
    //Do something with e 
    throw 
} 
+1

那么,远程访问服务的想法是测试一些以WCF客户端为中心的可伸缩性功能,所以我想对远程连接的测试覆盖范围进行测试。我不确定这是否是最好的方法,但是我喜欢代码覆盖范围... 如果我没有发现异常,测试失败,这对某些测试是准确的,但是在其他人,我真的很想测试错误是否被抛出。 – mattv 2011-04-06 11:22:47