简体   繁体   English

单元测试WCF故障

[英]Unit testing WCF Faults

What's the best way to unit test expected faults from WCF services? 从WCF服务单元测试预期故障的最佳方法是什么?

I am attempting to unit test a WCF service which is (correctly) throwing FaultExceptions for a certain reproducible error. 我正在尝试对WCF服务进行单元测试,该服务(正确地)抛出FaultExceptions以获得某个可重现的错误。 The unit tests get an instance of the WCF client and call the applicable service method, which throws a FaultException. 单元测试获取WCF客户端的实例并调用适用的服务方法,该方法抛出FaultException。

All of that works as you would expect, but I am having difficulty unit testing this, because the fault causes the IDE to break when the error isn't caught in the service implementation. 所有这些都可以按照您的预期运行,但是我对单元测试很困难,因为当服务实现中没有捕获到错误时,错误会导致IDE崩溃。 Because I am using faults, and not exceptions, I was expecting the IDE to serialize the exception and send it to the client, where it would raise an exception. 因为我使用的是故障而不是异常,所以我希望IDE能够序列化异常并将其发送到客户端,在那里它会引发异常。

I do see that there is a configuration option to disable breaking for specific user-unhandled exceptions, but I was hoping somebody could point out a better way to achieve the same results, as this isn't easily doable in a team environment. 我确实看到有一个配置选项来禁用特定用户未处理异常的中断,但我希望有人可以指出一种更好的方法来实现相同的结果,因为这在团队环境中不容易实现。

Here's some sample code of what the implementation currently looks like... 下面是一些示例代码,介绍了当前实现的内容......

The unit test project has a service reference to my WCF service, and I have defined the interface as such: 单元测试项目有一个对我的WCF服务的服务引用,我已经定义了这样的接口:

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

The fault is defined as such: 故障定义如下:

[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;
    }

}

The code that calls the service looks vaguely like this: 调用该服务的代码看起来像这样:

[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);
}
  • I edited the code to show that I am using the ExpectedException attribute and it doesn't seem to be having much effect on keeping the IDE/Debugger from breaking when the exception is thrown in the service. 我编辑了代码以显示我正在使用ExpectedException属性,并且当在服务中抛出异常时,它似乎没有对保持IDE / Debugger中断有太大影响。

You can always use ExpectedExceptionAttribute (in NUnit) to make sure this is the exception thrown. 您始终可以使用ExpectedExceptionAttribute (在NUnit中)来确保抛出此异常。 MSTest has similar concept as well. MSTest也有类似的概念。

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

If you have some Mock verification to do, I would use try/catch block and verify in the catch and then throw the exception. 如果你要做一些Mock验证,我会使用try / catch块并在catch中验证然后抛出异常。

UPDATE UPDATE

When you are using ExpectedException attribute, you are not supposed to catch the exception, instead you need to let the NUnit that runs your test to catch it. 当您使用ExpectedException属性时,您不应该捕获异常,而是需要让运行测试的NUnit捕获它。

If you need to verify special information in the exception then you catch the exception, verify the information and then rethrow: 如果您需要验证异常中的特殊信息,那么您将捕获异常,验证信息然后重新抛出:

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

}

mattv, mattv,

Why does this test has to access the service remotely ? 为什么此测试必须远程访问服务? From what I see your code: 从我看到你的代码:

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

Is somehow getting a service client, and not a service instance itself. 以某种方式获得服务客户端,而不是服务实例本身。 I'd advise to test the service concrete class directly for unit tests. 我建议直接测试服务具体类进行单元测试。

However, if you need this scenario, have you tried NOT CATCHING the exception and running the test? 但是,如果您需要此方案,您是否尝试过不捕获异常并运行测试? Does it give the same result? 它会给出相同的结果吗?

And by the way, if you need to catch and rethrow use the following pattern: 顺便说一句,如果你需要捕获并重新使用以下模式:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM