C#: xUnit 및 moq를 사용하여 여러 예외 테스트

18801 단어 moqxunittestingcsharp
이번 주에 조건에 따라 다른 유형의 Exception을 반환하는 메서드를 테스트하기 위해 단위 테스트 코드를 작성할 기회가 있었습니다. 여러 개[fact]를 작성할 수 있지만 간단하게 하기 위해 모든 예외 조합을 포함하기 위해 [theory]를 사용했습니다.

샘플 앱 만들기



간단한 앱을 만들어 봅시다. 내가 한 일을 설명하고 싶기 때문에 하나의 프로젝트만 추가합니다.

1. xunit 프로젝트를 생성하고 nuget을 추가합니다.

dotnet new xunit -n myexceptiontest
dotnet add .\myexceptiontest\myexceptiontest.csproj package moq
start .\myexceptiontest\myexceptiontest.csproj


2. 일부 조건으로 예외를 발생시키는 새로운 서비스 클래스를 추가합니다.

// MyService.cs
using System;

namespace myexceptiontest;

public interface IMyService
{
    public int MyMethod(int input);
}

public class MyService : IMyService
{
    public int MyMethod(int input)
    {
        switch (input)
        {
            case 1:
                throw new ArgumentException();
            case 2:
                throw new DivideByZeroException();
            case 3:
                throw new InvalidCastException();
            default:
                return input * 2;
        }
    }
}


서비스 단위 테스트



쓰기 팩트 단위 테스트



먼저 UnitTest1.cs 파일에 테스트[Fact]를 추가합니다.

using Moq;
using System;
using Xunit;

namespace myexceptiontest;

public class UnitTest1
{
    [Fact]
    public void Test1()
    {
        // arrange
        int input = 10;
        MyService myService = new MyService();

        // act
        int result = myService.MyMethod(input);
        Assert.Equal(20, result);
    }

    [Fact]
    public void TestException1()
    {
        // arrange
        int input = 1;
        MyService myService = new MyService();

        // act and assert
        Exception ex = Assert.Throws<ArgumentException>(()=> myService.MyMethod(input));
    }

    [Fact]
    public void TestException2()
    {
        // arrange
        int input = 2;
        MyService myService = new MyService();

        // act and assert
        Exception ex = Assert.Throws<DivideByZeroException>(() => myService.MyMethod(input));
    }
}


다중 예외 테스트에 이론 사용



이제 일부 시나리오를 지원하기 위해 [Theory]를 사용합니다.

[Theory]
[InlineData(1, typeof(ArgumentException))]
[InlineData(2, typeof(DivideByZeroException))]
[InlineData(3, typeof(InvalidCastException))]
public void TestExceptions(int input, Type exceptionType)
{
    // arrange
    MyService myService = new MyService();

    // act and assert
    Exception ex = Assert.Throws(exceptionType, ()=> myService.MyMethod(input));
}


클래스 단위 테스트



분명히 서비스를 사용할 클래스가 있습니다. 지금 추가해 보겠습니다.

namespace myexceptiontest;

public class MyClass
{
    private readonly IMyService myService;

    public MyClass(IMyService myService)
    {
        this.myService = myService;
    }

    public int Do(int input)
    {
        return this.myService.MyMethod(input);
    }
}


쓰기 팩트 단위 테스트



먼저 [Fact] 테스트를 추가합니다. 모의를 사용하여 MyService 동작을 제어합니다.

[Fact]
public void MyClassException1()
{
    // arrange
    Mock<IMyService> mockedIMyService = new Mock<IMyService>();
    mockedIMyService.Setup(x=>x.MyMethod(It.IsAny<int>())).Throws<ArgumentException>();
    MyClass myClass = new MyClass(mockedIMyService.Object);

    // act and assert
    Exception ex = Assert.Throws<ArgumentException>(() => myClass.Do(1));
}

[Fact]
public void MyClassException2()
{
    // arrange
    Mock<IMyService> mockedIMyService = new Mock<IMyService>();
    mockedIMyService.Setup(x => x.MyMethod(It.IsAny<int>())).Throws<DivideByZeroException>();
    MyClass myClass = new MyClass(mockedIMyService.Object);

    // act and assert
    Exception ex = Assert.Throws<DivideByZeroException>(() => myClass.Do(1));
}


다중 예외 테스트에 이론 사용



moq로 특정 예외 인스턴스를 발생시키려면 해당 유형의 인스턴스를 전달해야 합니다. 그러나 InlineData는 인스턴스 데이터를 허용하지 않습니다. 따라서 인스턴스를 전달할 수 있는 MemberData를 대신 사용했습니다.

[Theory]
[MemberData(nameof(InputAndException))]
public void MyClassExceptions(int input, Exception exception)
{
    // arrange
    Mock<IMyService> mockedIMyService = new Mock<IMyService>();
    mockedIMyService.Setup(x => x.MyMethod(input)).Throws(exception);
    MyClass myClass = new MyClass(mockedIMyService.Object);

    // act and assert
    Exception ex = Assert.Throws(exception.GetType(), () => myClass.Do(input));
}

private static IEnumerable<object[]> InputAndException()
{
    yield return new object[] { 1, new ArgumentException("dummy") };
    yield return new object[] { 2, new DivideByZeroException("dummy") };
    yield return new object[] { 3, new InvalidCastException("dummy") };
}


요약



xUnit의 이론은 입력 데이터로 테스트할 수 있는 여러 가지 방법을 제공합니다.

같은 것을 달성하는 더 좋은 방법이 있을 수 있으므로 아이디어가 있으면 알려주십시오.

좋은 웹페이지 즐겨찾기