NUnit结果在调试和发布方面有所不同

时间:2014-11-25 21:58:22

标签: c# unit-testing binding nunit tracelistener

我无法摆脱这个问题。这是非常有趣的,当我尝试在调试模式下运行我的NUnit测试时,我得到了预期的结果,但是当我正常运行时,结果是错误的。

我试图做的是检测绑定错误。这是一个样本

[TestFixture, RequiresSTA]
public class BindingTests
{
    [Test]
    public void T1_BindingErrorsExpected()
    {
        string error = null;
        using (var listener = new ObservableTraceListener())
        {
            listener.TraceCatched += s => error = s;

            TextBlock myText = new TextBlock();
            UserControl control = new UserControl();
            Binding myBinding = new Binding("BadBinding");
            myBinding.Source = control;
            myText.SetBinding(TextBlock.BackgroundProperty, myBinding);
        }
        Assert.IsNotNull(error);
    }
}

ObservableTraceListener

public sealed class ObservableTraceListener : DefaultTraceListener
{
    private readonly StringBuilder _Builder = new StringBuilder();
    public ObservableTraceListener()
    {
        PresentationTraceListener.Add(SourceLevels.Error, this);
    }

    public new void Dispose()
    {
        Flush();
        Close();
        PresentationTraceListener.Remove(this);
        base.Dispose();
    }   

    public override void Write(string message)
    {
        _Builder.Append(message);
    }

    public override void WriteLine(string message)
    {
        Write(message);

        if (TraceCatched != null)
            TraceCatched(_Builder.ToString());

        _Builder.Clear();
    }

    public event Action<string> TraceCatched;
}


public static class PresentationTraceListener
{
    public static void Add(SourceLevels level, TraceListener trace)
    {
        PresentationTraceSources.DataBindingSource.Listeners.Add(trace);
        PresentationTraceSources.DataBindingSource.Switch.Level = level;
        PresentationTraceSources.ResourceDictionarySource.Listeners.Add(trace);
        PresentationTraceSources.ResourceDictionarySource.Switch.Level = level;
    }

    public static void Remove(TraceListener trace)
    {
        PresentationTraceSources.DataBindingSource.Listeners.Remove(trace);
        PresentationTraceSources.ResourceDictionarySource.Listeners.Remove(trace);
    }
}

调试结果 - &gt;失败(我的期望)

运行结果 - >成功(不是预期的)

2 个答案:

答案 0 :(得分:1)

感谢MatthewMartin,但我找到了https://github.com/bblanchon/WpfBindingErrors

的解决方案

探测器是我的ObservableTraceListener

我需要添加一个静态构造函数来调用PresentationTraceSources.Refresh()以使其正常工作。如MSDN doc中所述,它Refreshes trace sources, by forcing the app.config file to be re-read。因此,当我在“调试”模式下启动测试时,刚刚完成了一些初始化,这可能导致app.config文件被读取。

MSDN doc - &gt; PresentationTraceSources.Refresh()http://msdn.microsoft.com/en-us/library/system.diagnostics.presentationtracesources.refresh%28v=vs.100%29.aspx

以下是我的最终ObservableTraceListenerPresentationTraceListener与问题中的public sealed class ObservableTraceListener : TraceListener { private readonly StringBuilder _Builder = new StringBuilder(); static ObservableTraceListener() { PresentationTraceSources.Refresh(); } public ObservableTraceListener() { PresentationTraceListener.Add(SourceLevels.Error, this); } public new void Dispose() { Flush(); Close(); PresentationTraceListener.Remove(this); base.Dispose(); } public override void Write(string message) { _Builder.Append(message); } public override void WriteLine(string message) { _Builder.Append(message); if (TraceCatched != null) TraceCatched(_Builder.ToString()); _Builder.Clear(); } public event Action<string> TraceCatched; } 相同

{{1}}

答案 1 :(得分:0)

发布答案,因为评论太小而无法保持我想说的内容......

Internet上没有对PresentationTraceListener的引用 - 它如何处理TraceListener很重要,因为AFAIK的PresentationTraceListener调用TraceListener的Write / WriteLine方法(可能通过TraceSource间接调用)

以下代码汇编了一个全新的项目。如果我写(x),我得到null,如果我写了线(x),我得到一个值。通常,当您编写自定义TraceListener时,将所有重载重定向到单个方法,以使它们的行为相同(Write和WriteLine应该相同,除了WriteLine在调用者的消息上添加换行符。)

另一个观察结果是,System.Diagnostics跟踪是一个古怪的日志记录库,其主要优点是即使在使用第三方库时存在一些障碍时它也始终可用。 System.Diagnostics跟踪确实希望您在app.config或web.config中注册TraceSwitch,TraceListener并使用它来启用&amp;禁用跟踪。它还要求注册TRACE标志(以相同的方式注册DEBUG标志,在项目中的特性 - 默认为DEBUG和RELEASE定义TRACE)

[TestFixture, RequiresSTA]
public class BindingTests
{
    [Test]
    public void T1_BindingErrorsExpected()
    {
        string error = null;
        using (var listener = new ObservableTraceListener())
        {
            listener.TraceCatched += s => error = s;

            //TextBlock myText = new TextBlock();
            //UserControl control = new UserControl();
            //Binding myBinding = new Binding("BadBinding");
            //myBinding.Source = control;
            //myText.SetBinding(TextBlock.BackgroundProperty, myBinding);
            PresentationTraceSources.DataBindingSource.TraceEvent(TraceEventType.Error,0, "Hello World!");    
        }
        Assert.IsNotNull(error);
        Console.WriteLine(error);

    }
}

public sealed class ObservableTraceListener : TraceListener
{
    private readonly StringBuilder _Builder = new StringBuilder();
    public ObservableTraceListener()
    {
        //PresentationTraceListener.Add(SourceLevels.Error, this);
    }
    protected override void Dispose(bool disposing)
    {
        Flush();
        Close();
        //PresentationTraceListener.Remove(this);
    }

    public override void Write(string message)
    {
        _Builder.Append(message);
    }

    public override void WriteLine(string message)
    {
        Write(message);

        if (TraceCatched != null)
            TraceCatched(_Builder.ToString());

        _Builder.Clear();
    }

    public event Action<string> TraceCatched;
}