.NET 单元测试运行程序输出FaultException.Detail

发布于 2024-10-11 08:54:53 字数 1452 浏览 5 评论 0原文

我正在 WCF 服务上运行一些单元测试。该服务配置为在故障响应中包含异常详细信息(在我的服务配置文件中包含以下内容)。

<serviceDebug includeExceptionDetailInFaults="true" />

如果测试导致服务器上出现未处理的异常,则客户端会通过完全填充的服务器堆栈跟踪接收到该故障。我可以通过调用异常的 ToString() 方法来看到这一点。问题是,这似乎不是我尝试过的任何测试运行程序(xUnit、Gallio、MSTest)的输出。它们似乎只输出异常的 Message 和 StackTrace 属性。

为了说明我的意思,以下单元测试将输出三个部分:

  • 错误消息
  • 错误堆栈跟踪
  • 标准控制台输出(包含我想要的信息,例如 “Fault Detail 等于 An ExceptionDetail,可能由 IncludeExceptionDetailInFaults=true 创建,其值为:...”

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

编辑: 但是,我希望我不必被迫在每个测试中捕获异常并将其按顺序写入控制台确定 FaultException 对象的 Detail 属性中的内容。

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

拥有此信息将使测试和部署的初始阶段变得不那么痛苦。

例如 em>我知道我可以将每个单元测试包装在通用异常处理程序中,并将异常写入控制台并在所有单元测试中重新抛出(如上所述),但这似乎 这是实现这一目标的一种非常冗长的方法(并且看起来非常糟糕)。

有谁知道是否有任何方法可以在未处理时获取此信息出现异常?有我缺少的设置吗?我的服务配置是否缺乏正确的故障处理?也许我可以为某些单元测试框架编写某种插件/适配器?也许我应该使用不同的单元测试框架!

我的实际设置是通过 Gallio 在开发环境中执行 xUnit 单元测试,但我确实编写了一套单独的“冒烟测试”,我希望能够让我们的工程师通过 xUnit GUI 测试运行程序(或Gallio 或其他)来简化最终部署。

谢谢。

亚当

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

夏末染殇 2024-10-18 08:54:53

我想我已经找到了解决方案。 Oleg Sych 实现了一种 WCF 行为,该行为透明地将异常从服务器编组到客户端,在客户端上引发异常,就像它们发生在那里一样。

就像向服务契约(接口)添加服务行为属性一样简单。

如果决定编写在单个进程中执行的现有代码应通过 WCF 服务进行分发,则此方法特别有用。这意味着无需对客户端的异常处理进行任何更改即可实现此目的(例如,您仍然可以在客户端上处理 SecurityException 而不必处理 FaultException 当您转向更加分布式的设计时)。

该帖子可以在这里找到:http://www .olegsych.com/2008/07/simplifying-wcf-using-exceptions-as-faults/

由于我的 WCF 服务混合使用 ws2007HttpBinding 和 basicHttpBinding (为了实现互操作性),我必须对代码(如上面帖子的评论中所述)。具体来说:

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

...以及在 ExceptionMarshallingMessageInspector.ReadFaultDetail 中,我进行了更改,以便它查找本地名称等于“Detail”的详细节点“(对于 ws2007HttpBinding”或“detail”(对于 basicHttpBinding)。

我希望这会有所帮助。

Adam

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

红颜悴 2024-10-18 08:54:53

控制台输出作为“测试结果”窗口中的一列提供。

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

独孤求败 2024-10-18 08:54:53

默认情况下,Gallio 将控制台输出重定向到其诊断日志。所以你应该直接在测试报告中看到你需要的信息。

例如,在 HTML 报告的“详细信息”部分中,展开测试树并找到您的测试方法。

Gallio 测试报告中的控制台输出

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文