MSTest 단위 테스트에서 "예외가 발생하지 않음"을 어떻게 확인합니까?


88

"void"를 반환하는이 메서드에 대한 단위 테스트를 작성 중입니다. 예외가 발생하지 않았을 때 테스트가 통과하는 경우를 하나 갖고 싶습니다. C #으로 어떻게 작성합니까?

Assert.IsTrue(????)

(내 생각 엔 이것이 내가 확인해야하는 방법이지만 "???"에 들어가는 내용)

내 질문이 충분히 명확하기를 바랍니다.


MSTest 또는 NUnit을 사용하고 있습니까?
Matt Grande

2
MSTest에서 포착되지 않은 예외로 인해 자동으로 테스트가 실패합니다. 포착 된 예외를 설명하려고합니까?

"try-catch for C #"을 검색하면 throw되거나 throw되지 않는 예외를 처리하는 방법을 알려줍니다.
Foggzie 2012

1
NUnit의 경우 Assert.That (lambda) .Throws.Nothing (최근 변경된 것 같지만)을 살펴보십시오
Matt Grande

답변:


138

예외가 발생하면 단위 테스트는 실패합니다. 특별한 어설 션을 입력 할 필요가 없습니다.

이것은 어설 션이 전혀없는 단위 테스트를 볼 수있는 몇 안되는 시나리오 중 하나입니다. 예외가 발생하면 테스트가 암시 적으로 실패합니다.

그러나 만약 당신이 정말로 이것에 대한 주장을 작성하고 싶었다면-아마도 예외를 잡아 내고 "예외를 예상했지만 이것을 얻었습니다 ..."를보고 할 수 있다면, 다음과 같이 할 수 있습니다 :

[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의 경우도 마찬가지입니다.)


분명히 이것이 사실을 유지하기 위해 그러한 예외를 포착해서는 안됩니다.
Servy

7
포착되지 않은 예외가 발생하는 경우에만 테스트가 실패합니다. 예외 처리기 내의 코드에 따라 단위 테스트가 통과 될 수 있습니다.
ediblecode

1
. 너무 유닛 테스트에는 Assert.DoesNotThrow (() 메소드가 없다, 미스 유닛 테스트를 위해 유용
사르 가야

25

NUnit에서는 다음을 사용할 수 있습니다.

Assert.DoesNotThrow(<expression>); 

코드에서 예외가 발생하지 않는다고 주장합니다. Assert가 없어도 예외가 발생하면 테스트가 실패하지만,이 접근 방식의 가치는 테스트에서 충족되지 않은 기대치와 버그를 구별 할 수 있고 다음과 같은 사용자 지정 메시지를 추가 할 수 있다는 것입니다. 테스트 출력에 표시됩니다. 잘 구성된 테스트 출력은 코드에서 테스트 실패를 유발 한 오류를 찾는 데 도움이 될 수 있습니다.

코드가 예외를 던지지 않도록 테스트를 추가하는 것이 타당하다고 생각합니다. 예를 들어 입력의 유효성을 검사하고 들어오는 문자열을 long으로 변환해야한다고 가정합니다. 문자열이 null 인 경우가있을 수 있으며 이는 허용 가능하므로 문자열 변환에서 예외가 발생하지 않도록해야합니다. 따라서이 경우를 처리 할 코드가 있으며 테스트를 작성하지 않은 경우 중요한 논리 부분에 대한 커버리지가 누락됩니다.


1
명시적인 DoesNotThrow가 좋습니다. 테스트에서 Assert. *를 보는 것에 익숙하다면 다른 사람이 게으르고 잊었다 고 생각할 수 있습니다.
Matt Beckman

vstest 또는 mstest에 이에 상응하는 것이 있습니까?
Dan Csharpster

1
@DanCsharpster, 적어도 MSTest에는 없다고 생각합니다. 과거에 MSTest에서이 기능이 필요했을 때 다음과 같이했습니다. public class TestBase { //believe me, I don't like this anymore than you do. protected void AssertDoesNotThrow(Action action, string message) { try { action(); } catch (Exception) { Assert.Fail(message); } } }
Clarkeye

@Clarkeye, 흥미로운 아이디어입니다. 감사! 바라건대, 그들은 향후 버전에서 NUnit을 더 잘 복사하는 법을 배울 것입니다. 또한 vstest와 NUnit 사이에 어댑터를 작성하는 것도 고려했습니다.
Dan Csharpster

@DanCsharpster, 한 가지 살펴보고 싶은 것은 유창한 주장이며, ShouldThrow 및 ShouldNotThrow를 잘 지원합니다 : github.com/dennisdoomen/fluentassertions/wiki#exceptions . 문서는 MSTest와 호환된다고 말합니다 (하지만 XUnit 및 NUnit에서만 사용했습니다). 원하는 모든 것을 할 수는 없지만 어쨌든 MSTest 어설 션과 혼합 할 수 있습니다.
Clarkeye

11

어떤 일이 일어나지 않는다는 것을 테스트하지 마십시오 . 코드 가 깨지지 않도록 하는 것과 같습니다 . 그것은 일종의 암시 적이며, 우리 모두는 깨지지 않는 버그없는 코드를 위해 노력합니다. 그것에 대한 테스트를 작성하고 싶습니까? 왜 한 가지 방법일까요? 모든 메서드가 예외를 throw하지 않도록 테스트하고 싶지 않습니까? 그 길을 따라 가면 코드베이스의 모든 메서드에 대해 하나의 추가 더미, 어설 션없는 테스트 로 끝납니다 . 가치가 없습니다.

물론, 메서드 예외를 포착 하는지 확인하는 것이 요구 사항이라면 이를 테스트 (또는 약간 반전하고 포착해야하는 것을 던지지 않는지 테스트)합니다.

그러나 일반적인 접근 방식 / 관행은 그대로 유지됩니다. 테스트 된 코드의 범위를 벗어난 일부 인위적 / 모호한 요구 사항에 대한 테스트를 작성하지 않습니다. 특히 방법의 책임이 잘 알려진 시나리오에서).

간단하게 말하면 코드 가 수행 해야하는 작업에 집중 하고이를 테스트합니다.


10
-1 예외를 던지지 않고 요구하는 긍정적 인 기능을 생각할 수 있습니다. 예외를 처리하는 것이 작업 인 하나의 메서드의 경우 예외를 더 이상 발생시키지 않고 예외를 기록하고 조치를 취합니다. 당신은 좋은 일반적인 요점을 만들지 만 그것이 항상 사실 인 것처럼 절대적 으로 말하십시오 .
Rob Levine

3
@RobLevine : 나는 당신의 예를 이해하고 그러한 경우에 테스트를 작성한다는 것을 알고 있습니다. 그러나 눈치 채셨 듯이 제 요점은 실제로 더 일반적인 관행에 관한 것입니다. 말하자면, 코드가 수행해야하는 작업과 코드가 수행하지 않는 작업을 테스트하는 것입니다. 나는 내 글을 약간 바꿔서 내 요점이 내가 생각했던 것에 더 명확하고 더 가깝게 만들었다. 또한 귀하의 투표를 재고 할 기회를 제공합니다. 설명해 주셔서 감사 드리며 답변이 지연되어 죄송합니다.
km

4
downvote 제거됨-다음 번에 down-vote에서 그렇게 행복하지 않을 것입니다!
Rob Levine

4
우리 프로젝트에는 html이 유효하지 않은 경우 예외를 발생시키는 htmlvalidator 클래스가 있습니다. 예를 들어 사용자 입력 (콘솔 사용) javascript가 풍부한 콤보로 제공됩니다. 그래서 내 경우 코드에서 내 코드가하는 일은 예외 (화이트리스트 접근 방식)를 던지지 않는 것이며이를 테스트해야합니다.
Machet 2014-10-29

1
이 답변에 동의하지 않습니다. 때로는 특정 시나리오에서 무언가가 없는지 테스트하는 것이 유효한 테스트가 될 수 있습니다.
bytedev

7

이 도우미 클래스는 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);
        }
    }
}

@Remco Beurskens-NoExceptionThrown <T> 끝에 일반 catch {}를 추가하면 메서드의 의도 된 결과가 아닌 다른 오류가 억제됩니다. 이것은 모든 예외를 억제하는 범용 방법이 아닙니다. 알려진 유형의 예외가 발생하는 경우에만 실패합니다.
JJS

1
이것은 현재 매우 오래되었지만 확장 메서드에 대한 후크로 사용할 수 Assert있는 단일 속성 접근 That자를 가지고 있습니다. 그것은 깔끔한 수 있습니다, 그리고 더 많은 검색 가능하도록 Assert.That.DoesNotThrow()보다는 AssertEx.DoesNotThrow(). 이것은 단지 의견입니다.
Richard Hauer 19 년

3

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

    }

이건 같은게 아니야. 코드가 throw되면 어설 션이 적중되지 않고 테스트 실행이 실패합니다. 조건을 어설 션하여 테스트 프레임 워크에 연결하려고합니다.
DvS

1

내 친구 Tim이 ExpectedException 에 대해 나에게 말했다 . 나는이 b / c가 더 간결하고 코드가 적으며 예외를 테스트하고 있다는 것이 매우 분명합니다.

[TestMethod()]
[ExpectedException(typeof(System.Exception))]
public void DivideTest()
{
    int numerator = 4;
    int denominator = 0;
    int actual = numerator / denominator;
}

여기에서 더 많은 것을 읽을 수 있습니다 : ExpectedException Attribute Usage .


1
OP는 예외 없음을 요구하고 있습니다.
Daniel A. White

이 답변을 여기에 남겨 두겠습니다. 예외를 테스트하는 방법에 대해 Google을 검색하는 동안이 질문을 발견 했으며이 답변이 여기에 있어야한다고 생각합니다. OP는 7 년 전에 질문에 대한 답변을 받았습니다. 다른 답변에 대한 링크조차도 도움이된다고 생각합니다.
Jess

좋은 ole Tim. 🤔
ruffin
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.