2012-02-23 39 views
51

我正在为这个返回“void”的方法写一个单元测试。我希望在没有异常抛出时测试通过一个案例。我如何在C#中编写?C#:如何在我的单元测试中检查“没有发生异常”?

Assert.IsTrue(????) 

(我的猜测是,这是我应该怎么检查,但什么进入“???”)

我希望我的问题是非常明显的。

+0

您使用的是MSTest还是NUnit? – 2012-02-23 16:41:22

+2

在MSTest中,未捕获的异常会自动导致测试失败。你是否试图解释捕获的异常? – Phil 2012-02-23 16:42:04

+0

您可以查看“try-catch for C#”,这将指导您如何处理抛出或不抛出的异常。 – Foggzie 2012-02-23 16:42:14

回答

81

如果抛出异常,你的单元测试将会失败 - 你不需要放置一个特殊的断言。

这是少数情况下你会看到没有断言的单元测试之一 - 如果引发异常,测试将隐式失败。

但是,如果你真的想要写这个断言 - 也许能够捕获异常,并报告“预计也不例外,但得到这个......”,你可以这样做:

[Test] 
public void TestNoExceptionIsThrownByMethodUnderTest() 
{ 
    var myObject = new MyObject(); 

    try 
    { 
     myObject.MethodUnderTest(); 
    } 
    catch (Exception ex) 
    { 
     Assert.Fail("Expected no exception, but got: " + ex.Message); 
    } 
} 

(以上是NUnit的示例,但对于MSTest也是如此)

+0

显然,你不应该去抓这些例外,以保持真实。 – Servy 2012-02-23 16:42:10

+5

只有在引发未捕获的异常时,测试才会失败。取决于异常处理程序中的代码,单元测试可能会通过。 – ediblecode 2012-02-23 16:43:05

9

不要测试那些东西doesn't happen。这就像确保代码不会中断。这是暗示的,我们都努力争取不间断的,无缺陷的代码。你想为它写测试吗?为什么只有一种方法?难道你不想让你的所有方法都被测试:他们不要抛出一些异常?在此之后,您将以代码库中的每种方法结束一个额外的虚拟测试,断言测试。它没有带来任何价值。

当然,如果您的要求是验证方法确实捕获异常,你测试(或逆转了一点,测试,它不会引发什么是应该抓)。

但是,一般方法/实践保持不变 - 您不会为某些超出测试代码范围的人为/模糊需求编写测试(并且测试“有效”或“不会丢失”是通常是这样的一个例子 - 特别是在方法的责任众所周知的情况下)。

说得简单 - 专注于你的代码必须做的并测试。

+4

-1我可以想到积极的功能,需要和异常不会被抛出。对于处理异常的单一方法,记录它们并采取行动 - 而不会进一步抛出异常。你提出了一个很好的总体观点 - 然后在_absolute_中说话,就好像它总是如此。 – 2012-02-23 20:19:51

+0

@RobLevine:当你的例子在记录时抛出会发生什么?你是否断言它并没有对此进行测试?这是我的全部观点。我并不是想要听起来“宗教”(我也不理解downvote的理由),但断言某些事情没有发生*,总的来说,这很**适得其反。你通常想要相反,断言你的代码*做某事*。这很简单。 – 2012-02-24 01:43:30

+0

我明白你的意思 - 这是很好的_通用建议。麻烦的是,从绝对开始的那一刻,就会损害核心点。如果被测代码的性质是_prevent_抛出异常,那么这是一个_positive_断言,以确保没有抛出异常。在一般情况下,你的整体观点是好的,但我认为这是你设计它的方式,这让我觉得它总体上是无益的建议。 -1有点严厉 - 几分钟后我改变了主意,但除非您再次编辑帖子,否则它不会让我+1。对于那个很抱歉。 – 2012-02-24 10:13:07

16

在NUnit的,你可以使用:

Assert.DoesNotThrow(<expression>); 

断言,您的代码不会抛出异常。虽然如果即使周围没有Assert也会抛出异常,测试会失败,但这种方法的价值在于,您可以区分未满足的期望和测试中的错误,并且您可以选择添加自定义消息将显示在您的测试输出中。措辞良好的测试输出可以帮助您找到代码中导致测试失败的错误。

我认为这是有效的添加测试,以确保您的代码不引发异常;例如,假设您正在验证输入并需要将传入的字符串转换为长整型。有时可能会出现字符串为空的情况,这是可以接受的,所以您希望确保字符串转换不会引发异常。因此将会有代码来处理这种情况,如果你没有为它写一个测试,你将错过围绕一个重要逻辑的覆盖。

+1

明确的DoesNotThrow很好。如果你习惯在测试中看到Assert。*,你可能会认为另一个人很懒,并且忘记了。 – 2014-06-11 18:04:12

+0

在vstest或mstest中是否有任何等价物? – 2015-03-12 18:40:20

+1

@DanCsharpster,我不认为至少在MSTest中 - 当我在过去需要MSTest中的这个功能时,我做了这样的事情: 'public class TestBase { // believe我,我不喜欢这个,比你更喜欢。 保护无效AssertDoesNotThrow(动作动作,字符串消息) { 尝试 { action(); (例外) } catch(例外) Assert.Fail(message); } } }' – Clarkeye 2015-03-27 11:19:49

3

这个帮助类使用MSTest来抓我的痒。也许它也可以抓你的。

[TestMethod] 
public void ScheduleItsIneligibilityJob_HasValid_CronSchedule() 
{ 
    // Arrange 
    var factory = new StdSchedulerFactory(); 
    IScheduler scheduler = factory.GetScheduler(); 

    // Assert 
    AssertEx.NoExceptionThrown<FormatException>(() => 
     // Act 
     _service.ScheduleJob(scheduler) 
    ); 
} 

public sealed class AssertEx 
{ 
    public static void NoExceptionThrown<T>(Action a) where T:Exception 
    { 
     try 
     { 
      a(); 
     } 
     catch (T) 
     { 
      Assert.Fail("Expected no {0} to be thrown", typeof(T).Name); 
     } 
    } 
} 
1

我最喜欢看的Assert.Whatever在每次测试结束,只为一致性......没有一个,我真的能确定自己不应该是一个人也没有?

对于我来说,这是把Assert.IsTrue(true);

简单我知道我没有意外把这些代码在那里,因此我应该在一个快速通过,这是脱脂有足够的自信如预期。

[TestMethod] 
    public void ProjectRejectsGappedVersioningByDefault() { 

     var files = new List<ScriptFile>(); 
     files.Add(ScriptProjectTestMocks.GetVersion1to2()); 
     files.Add(ScriptProjectTestMocks.GetVersion3to4()); 

     Assert.Throws<ScriptProject.InvalidProjectFormatException>(() => { 
      var sut = new ScriptProject(files); 
     }); 

    } 

    [TestMethod] 
    public void ProjectAcceptsGappedVersionsExplicitly() { 

     var files = new List<ScriptFile>(); 
     files.Add(ScriptProjectTestMocks.GetVersion1to2()); 
     files.Add(ScriptProjectTestMocks.GetVersion3to4()); 

     var sut = new ScriptProject(files, true); 

     Assert.IsTrue(true); // Assert.Pass() would be nicer... build it in if you like 

    } 
相关问题