2015-01-26 74 views
5

我有例外单元测试异常财产

class SyntaxError : Exception { 
    public SyntaxError(int l) { 
     line = l; 
    } 
    public int line; 
} 

我使用单元测试来测试类解析器在特定的输入应该抛出上面的异常。我正在使用这样的代码:

[TestMethod] 
    [ExpectedException(typeof(Parser.SyntaxError))] 
    public void eolSyntaxError() 
    { 
     parser.reader = new StringReader("; alfa\n; beta\n\n\n\na"); 
     parser.eol(); 
    } 

是否有任何智能简单的方法来检查是否SyntaxError.line == 1

最好的我想出是:

[TestMethod] 
    public void eolSyntaxError() 
    { 
     try { 
      parser.reader = new StringReader("; alfa\n; beta\n\n\n\na"); 
      parser.eol(); 
      Assert.Fail(); 
     } catch (SyntaxError e) { 
      Assert.AreEqual(1, e.line); 
     } 
    } 

我不很喜欢,有没有更好的办法?

+1

你不喜欢它使用它? – 2015-01-26 21:41:11

+0

这似乎必须有更简单的方法,它看起来像这么简单的东西太多代码..但如果这是最好的方式,我会这样做它 – Paladin 2015-01-26 21:42:28

+0

如果行值的状态是相关的时间抛出异常,然后将其作为参数包含在异常中。 – Matt 2015-01-26 21:43:01

回答

3

考虑使用FluentAssertions。然后,您的测试将如下所示:

[TestMethod] 
public void eolSyntaxError() 
{ 
    parser.reader = new StringReader("; alfa\n; beta\n\n\n\na"); 

    Action parseEol =() => parser.eol(); 

    parseEol 
     .ShouldThrow<SyntaxError>() 
     .And.line.Should().Be(1); 
} 

否则,您的方法非常好。

+0

感谢提示,如果我需要更复杂的东西,这看起来不错,但对于我的(有限)使用情况,它是很多代码,我的try/catch可能更短.. +其中一个评论建议更好的解决方案(为我的需要) – Paladin 2015-01-26 22:02:09

+2

@Paladin:没问题。我会建议*反对*滚动自己的断言逻辑(如其他答案可能表明的那样);或者坚持用'try-catch'(你的情况可能足够好)或者使用第三方库(比如FluentAssertions) - 不要重新发明轮子。 – 2015-01-26 22:05:46

1

根据我的评论,如果遇到语法错误的行是相关的,那么将其包含在您的自定义异常类中,就像这样。

public class SyntaxError : Exception 
{ 
    public SyntaxError(int atLine) 
    { 
     AtLine = atLine; 
    } 

    public int AtLine { get; private set; } 
} 

然后很容易测试。

编辑 - 在阅读问题(!)后,这里有一个简单的附加Assert方法,它将清理异常声明。

public static class xAssert 
{ 
    public static TException Throws<TException>(Action a) where TException : Exception 
    { 
     try 
     { 
      a(); 
     } 
     catch (Exception ex) 
     { 
      var throws = ex as TException; 
      if (throws != null) 
       return throws; 
     } 
     Assert.Fail(); 
     return default(TException); 
    } 
} 

用法如下...

public class Subject 
{ 
    public void ThrowMyException(int someState) 
    { 
     throw new MyException(someState); 
    } 

    public void ThrowSomeOtherException() 
    { 
     throw new InvalidOperationException(); 
    } 
} 

public class MyException : Exception 
{ 
    public int SomeState { get; private set; } 

    public MyException(int someState) 
    { 
     SomeState = someState; 
    } 
} 

[TestClass] 
public class UnitTest1 
{ 
    [TestMethod] 
    public void TestMethod1() 
    { 
     var subject = new Subject(); 
     var exceptionThrown = xAssert.Throws<MyException>(() => { subject.ThrowMyException(123); }); 

     Assert.AreEqual(123, exceptionThrown.SomeState); 
    } 
} 
+0

他已经在做这个 – 2015-01-26 21:47:11

+0

对不起@Matt,你对这个问题的解决方案是什么? – 2015-01-26 21:47:40

+0

我绝对可以做到这一点,我已经有'公共诠释线'...但它将如何帮助我测试它? – Paladin 2015-01-26 21:47:58

0

我不知道的出来这个现成的解决方案的,但我所看到的期望,其工作是这样的概念:

[TestMethod] 
public void EolSyntaxError() 
{ 
    Expectations.Expect<(SyntaxError>(
     () => 
     { 
      parser.reader = new StringReader("; alfa\n; beta\n\n\n\na"); 
      parser.eol(); 
     }, 
     e => 
     { 
      Assert.AreEqual(1, e.line); 
     }); 
} 

期望需要实施。我认为那里会有图书馆已经这样做了。总之,在ExpectationsExpect方法看起来是这样的:

public static void Expect<TExpectedException>(
    System.Action action, 
    System.Action<TExpectedException> assertion) where TExpectedException : Exception 
{ 
    if (action == null) { throw new ArgumentNullException("action"); } 
    try 
    { 
     action.Invoke(); 
     Assert.Fail(string.Format("{0} expected to be thrown", typeof(TExpectedException).Name)); 
    } 
    catch (TExpectedException e) 
    { 
     assertion.Invoke(e); 
    } 
} 
3

你可以写一个类似的NUnit的

public T Throws<T>(Action code) where T : Exception 
{ 
    Exception coughtException = null; 
    try 
    { 
     code(); 
    } 
    catch (Exception ex) 
    { 
     coughtException = ex; 
    } 

    Assert.IsNotNull(coughtException, "Test code didn't throw exception"); 
    Assert.AreEqual(coughtException.GetType(), typeof(T), "Test code didn't throw same type exception"); 

    return (T)coughtException; 
} 

的方法,然后你可以在你的测试方法

Parser.SyntaxError exception = Throws<Parser.SyntaxError>(() => parser.eol()); 
Assert.AreEqual(1, exception.line);