Unit testing WCF Faults
Asked Answered
D

2

10

What's the best way to unit test expected faults from WCF services?

I am attempting to unit test a WCF service which is (correctly) throwing FaultExceptions for a certain reproducible error. The unit tests get an instance of the WCF client and call the applicable service method, which throws a 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. 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.

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:

[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.
Decurion answered 1/11, 2010 at 16:59 Comment(3)
Are you hosting the WCF service in the same process as the unit tests, or in a separate process?Discolor
Separate processes, the WCF service is hosted through IIS. I'm running the Unit Tests locally in debug mode. Both projects are part of the same solution. I think if I run the service in Build mode and the unit tests in Debug mode it would probably fix the problem, but that doesn't seem like a better solution then the IDE config option.. It's still something I have to do for everyone's machine.Decurion
Do you have the IDE configured to break on all exceptions?Dock
S
1

You can always use ExpectedExceptionAttribute (in NUnit) to make sure this is the exception thrown. MSTest has similar concept as well.

[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.

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.

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

}
Sunda answered 1/11, 2010 at 17:16 Comment(6)
I actually am using the ExpectedException attribute in the unit test. Perhaps I'm using it incorrectly. I'll append what I'm doing in the example code.Decurion
Well, thanks for informing me on the proper usage of the attribute - still doesn't address my issue, unfortunately. Although now the test passes when I resume the application after it breaks for the exception!Decurion
As I understood it, your problem was the test which I have given advice. You have not shared anything for the application problem, how do you think I should help you?Sunda
My problem is that the test causes the IDE to break when the exception occurs on the server side, not that I don't know how to assert a test has passed.Decurion
I said that here: "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." .... Don't get me wrong, I appreciate the help and you have shown me an error I was making, but my issue still exists.Decurion
This can only happen if you hit Ctrl+Alt+E and set it to break on exceptions. If it is not set like that, IDE should not break.Sunda
R
1

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
}
Rage answered 1/4, 2011 at 7:21 Comment(1)
Well, the idea behind accessing the service remotely is to test some scalability features that are centered around the WCF clients, so I want to have test coverage of how the remote connection is made. I'm not sure if this is the best way to do it, really, but I like the code coverage... If I don't catch the exception, the test fails, which is accurate for some tests, but in others, I'd really like to test that the error was thrown.Decurion

© 2022 - 2024 — McMap. All rights reserved.