C#

C# 기초부터 고급까지 Chapter 2.8. 테스트 코드 작성 기초 – xUnit 완전정복 편

Juan_ 2025. 5. 2. 22:25
728x90

📘 Chapter 2.8: 테스트 코드 작성 기초 – xUnit 완전정복 편


✅ 이 챕터에서 배울 것

  • 테스트 코드는 왜 필요한가?
  • xUnit 설치 및 설정
  • 기본 테스트 메서드 작성법
  • 테스트 클래스 구성
  • Assert 사용법
  • 데이터 기반 테스트 (Theory)
  • 의존성 있는 서비스 테스트하는 방법 (Mocking 개념 포함)

1️⃣ 테스트 코드, 왜 필요한데?


"코드가 돌아가는 게 아니라, 제대로 돌아가는지 확인하는 게 중요하다!"

상황 위험
리팩터링 시 기존 기능 깨질 수 있음 🚨 확인 불가
팀원이 수정한 코드, 예상과 다르게 동작 🚨 예외 발생
외부 API 변화 🚨 호출 실패

✅ 이걸 예방하려면?

→ 테스트 코드가 자동으로 돌면서 이상 여부를 알려줘야 한다!


2️⃣ xUnit 시작하기


✅ xUnit은 뭔데?

  • .NET 진영에서 가장 널리 쓰이는 단위 테스트 프레임워크
  • MSTest보다 표현력 강하고, NUnit보다 가볍고 직관적

🔧 설치 방법

  1. 테스트용 프로젝트 만들기:
dotnet new xunit -n MyApp.Tests
  1. 테스트 대상 프로젝트 참조 추가:
cd MyApp.Tests
dotnet add reference ../MyApp/MyApp.csproj

✅ 또는 솔루션에 둘 다 포함시키고, 참조 추가하면 됨!


3️⃣ 기본 테스트 작성 흐름


✅ 기본 구조

public class Calculator
{
    public int Add(int a, int b) => a + b;
}

✅ 테스트 코드

public class CalculatorTests
{
    [Fact]
    public void Add_두수를더하면_합계가나와야한다()
    {
        // Arrange (준비)
        var calculator = new Calculator();

        // Act (실행)
        int result = calculator.Add(2, 3);

        // Assert (검증)
        Assert.Equal(5, result);
    }
}

Fact = 인자가 없는 "단일 테스트 시나리오"


4️⃣ 다양한 Assert 사용법


메서드 설명
Assert.Equal(a, b) 값 비교
Assert.True(cond) 조건이 true인지
Assert.NotNull(obj) null이 아닌지
Assert.Throws 예외 발생하는지 확인

예외 테스트 예시

[Fact]
public void Divide_0으로나누면_예외발생해야함()
{
    var calc = new Calculator();

    Assert.Throws<DivideByZeroException>(() => calc.Divide(10, 0));
}

5️⃣ Theory + InlineData (데이터 기반 테스트)


public class Calculator
{
    public int Multiply(int a, int b) => a * b;
}
public class CalculatorTests
{
    [Theory]
    [InlineData(2, 3, 6)]
    [InlineData(4, 5, 20)]
    [InlineData(0, 99, 0)]
    public void Multiply_테스트(int a, int b, int expected)
    {
        var calc = new Calculator();

        var result = calc.Multiply(a, b);

        Assert.Equal(expected, result);
    }
}
  • Theory는 반복 테스트를 자동으로 돌려준다
  • InlineData는 매개변수를 테스트에 넣어준다

6️⃣ 의존성 있는 클래스 테스트: Mock 사용


예: UserService가 내부적으로 EmailService에 의존할 때

테스트 대상 클래스

public class UserService
{
    private readonly IEmailService _email;

    public UserService(IEmailService email)
    {
        _email = email;
    }

    public bool Register(string email)
    {
        _email.Send(email);
        return true;
    }
}

📦 Moq 설치

dotnet add package Moq

테스트 코드

public class UserServiceTests
{
    [Fact]
    public void Register_이메일전송호출되어야함()
    {
        // Arrange
        var mockEmail = new Mock<IEmailService>();
        var service = new UserService(mockEmail.Object);

        // Act
        var result = service.Register("test@example.com");

        // Assert
        mockEmail.Verify(e => e.Send("test@example.com"), Times.Once());
        Assert.True(result);
    }
}
  • ✅ 외부 의존성을 진짜 객체로 쓰지 않고, 가짜(Mock)로 바꿔서 테스트함
  • 행동(메서드 호출 여부) 도 검증 가능

✅ 정리 요약


항목 설명
Fact 단일 테스트
Theory + InlineData 매개변수 있는 반복 테스트
Assert 테스트 결과 검증
Moq 의존성(Mock 객체) 생성
xUnit 장점 직관적, 가볍고 널리 쓰임, 확장성 좋음

📢 다음 챕터 예고 🎓

다음 챕터 주제
Chapter 2.9 인터페이스 활용 – 다형성 실전 예제
728x90