Question

I am running some unit tests on a WCF service. The service is configured to include exception details in the fault response (with the following in my service configuration file).

<serviceDebug includeExceptionDetailInFaults="true" />

If a test causes an unhandled exception on the server the fault is received by the client with a fully populated server stack trace. I can see this by calling the exception's ToString() method. The problem is that this doesn't seem to be output by any of the test runners that I have tried (xUnit, Gallio, MSTest). They appear to just output the Message and the StackTrace properties of the exception.

To illustrate what I mean, the following unit test will output three sections:

  • Error Message
  • Error Stack Trace
  • Standard Console Output (contains the information I would like, e.g. "Fault Detail is equal to An ExceptionDetail, likely created by IncludeExceptionDetailInFaults=true, whose value is: ..."

public void Test()
{
    try
    {
        service.CallMethodWhichCausesException();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex); // this outputs the information I would like
       throw;
    }
}

Edit: However, I would prefer that I was not forced to catch the exception in each test and write it to the console in order to ascertain the content within a FaultException object's Detail property.

For example,

public void Test()
{
    service.CallMethodWhichCausesException();
}

Having this information will make the initial phase of testing and deployment a lot less painful.

I know I can just wrap each unit test in a generic exception handler and write the exception to the console and rethrow (as above) within all my unit tests but that seems a very long-winded way of achieving this (and would look pretty awful).

Does anyone know if there's any way to get this information included whenever an unhandled exception occurs? Is there a setting that I am missing? Is my service configuration lacking in proper fault handling? Perhaps I could write some kind of plug-in / adapter for some unit testing framework? Perhaps theres a different unit testing framework which I should be using instead!

My actual set-up is xUnit unit tests executed via Gallio for the development environment, but I do have a separate suite of "smoke tests" written which I would like to be able to have our engineers run via the xUnit GUI test runner (or Gallio or whatever) to simplify the final deployment.

Thanks.

Adam

Was it helpful?

Solution

I think I have found a solution. Oleg Sych has implemented a WCF behaviour which transparently marshals exceptions from the server to client, raising them on the client as if they had occurred there.

It's as simple as adding a service behaviour attribute to the service contract (interface).

This approach is especially beneficial if it is decided that existing code, written to execute within a single process, should distributed via WCF services. It means that it can be achieved without requiring any changes to the client's exception handling (e.g. you can still handle a SecurityException on the client instead of having to handle a FaultException<SecurityException> when you move to a more distributed design).

The post can be found here: http://www.olegsych.com/2008/07/simplifying-wcf-using-exceptions-as-faults/

Since my WCF services are using a mixture of ws2007HttpBinding the basicHttpBinding (for interoperability), I had to make a few changes to the code (as mentioned in the comments of the post above). Specifically:

In ExceptionMarshallingMessageInspector.AfterReceiveReply:

Exception exception = faultDetail as Exception;
if (exception != null)
{
    // NB: Error checking etc. excluded
    // Get the _remoteStackTraceString of the Exception class

    FieldInfo remoteStackTraceString = typeof(Exception).GetField(
        "_remoteStackTraceString",
        BindingFlags.Instance | BindingFlags.NonPublic);

    // Set the InnerException._remoteStackTraceString to the current InnerException.StackTrace
    remoteStackTraceString.SetValue(
        exception,
        exception.StackTrace + Environment.NewLine);

    throw exception;
}

...and in ExceptionMarshallingMessageInspector.ReadFaultDetail I made a change so that it looks for a detail node with a local name equal to either "Detail" (for ws2007HttpBinding" or "detail" (for basicHttpBinding).

I hope this helps.

Adam

OTHER TIPS

Console output is available as a column in the Test Results window.

Gallio redirects the console output to its diagnostic log by default. So you should see the information you need directly in the test report.

In the section Details of the HTML report for example, expand the test tree and locate your test method.

Console output in Gallio test report

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top