Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
635 views
in Technique[技术] by (71.8m points)

c# - Method for handling exceptions in mstest

I have a lot of tests writen in this format:

[TestMethod]
public void TestMethod1()
{
    try
    {
        DoShomething();
    }
    catch (Exception e)
    {
        WriteExceptionLogWithScreenshot( e );
    }
}

[TestMethod]
public void TestMethod2()
{
    try
    {
        DoAnotherShomething();
    }
    catch ( Exception e )
    {
        WriteExceptionLogWithScreenshot( e );
    }
}

I would like to unify this exception handling using something like

[TestCleanup]
public void Cleanup()
{
    // find out if an exception was thrown and run WriteExceptionLogWithScreenshot( e )
}

Then I could avoid writing try catch blocks in all methods.

Does mstest support something like this? anyone have an ideia about what I could do?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

While it is an easy and (thread) safe alternative to wrap the test code in a lambda like Kip's answer I've found that it makes the stack trace a little harder to read since you'll always have the anonomous labmda stuck in there. Also, it requires another nesting level and it just tickles my OCD nerves a little.

I'd love for this to be extensible in MSTest, and in something like XUnit or NUnit you can get around this. You could even do this Aspect Oriented by superimposing a wrapper method around each method being run using something like PostSharp (see here).

If you're stuck with MSTest for whatever reasons (we've got a few myself, "attaching" files, CI scripts having been setup etc) you could do this though.

Make use of the FirstChanceException which will catch any exception thrown. Now, what I propose here is not thread safe and a bit wacky but if you're like us, running single threaded tests and care more about ease of use than performance etc it might work for you, you could improve this by bundling the registrations etc with the test context.

Basically, what I did anyway is to have a global test class that hooks the FirstChanceExceptions and 'safekeeps' the last thrown exception, then I reference this in the cleanup method.

[TestClass]
public static class GlobalSetup
{
    [AssemblyInitialize]
    public static void Setup(TestContext context)
    {
        AppDomain.CurrentDomain.FirstChanceException += (s, e) => LastException = e.Exception;
    }

    public static Exception LastException { get; private set; }
}

Then in a base class which contains logic for cleaning up any test:

[TestCleanup]
public virtual void Cleanup()
{
    if (TestContext.CurrentTestOutcome != UnitTestOutcome.Passed && GlobalSetup.LastException != null)
    {
        var e = GlobalSetup.LastException;
        Log.Error(GlobalSetup.LastException, $"{e.GetType()}: {e.Message}
{e.StackTrace}");
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...