본문 바로가기
카테고리 없음

✅ 레거시 코드에서 TDD 적용하기 | 1편: MSTest 환경 설정 및 첫 테스트 작성 (.NET Framework 기준)

by bbongz 2025. 3. 25.

 

레거시 코드에서 TDD(Test-Driven Development)를 적용하는 것은 쉽지 않습니다. 특히 .NET Framework 기반 레거시 코드는 일반적으로 테스트 가능성이 낮고, 의존성이 강하게 얽혀 있는 경우가 많습니다.

이번 글에서는 .NET Framework + MSTest를 기반으로 레거시 코드에서 TDD를 적용하는 방법을 다룹니다.

  • ✅ 기존 레거시 코드를 테스트 가능하게 수정
  • ✅ Moq을 사용해 외부 의존성을 Mocking
  • ✅ MSTest로 첫 테스트 작성 및 성공시키기

🚀 1. TDD란 무엇인가?

TDD(Test-Driven Development)는 "테스트 주도 개발"을 의미합니다. 말 그대로 코드를 작성하기 전에 테스트 코드부터 작성하고, 테스트가 통과할 수 있도록 코드를 작성한 뒤 리팩토링하는 과정을 반복합니다.

TDD는 다음과 같은 3단계 사이클로 이루어집니다:

  1. RED – 실패하는 테스트 작성
  2. GREEN – 테스트가 통과하도록 코드 작성
  3. REFACTOR – 코드 리팩토링 및 성능 개선
"테스트가 코드보다 먼저 작성된다."

🚩 2. 레거시 코드에서의 문제점

레거시 코드에서 TDD 적용이 어려운 이유는 다음과 같습니다:

  • 테스트 코드가 작성되지 않은 상태
  • static 메서드 사용 → Mocking 불가능
  • 데이터베이스, 네트워크 등 외부 시스템에 의존
  • 비즈니스 로직이 직접 코드에 연결됨

🔥 레거시 코드 예제


public static class OrderService
{
    public static bool ProcessOrder(int orderId)
    {
        var order = Database.GetOrderById(orderId);
        if (order == null) return false;
        
        PaymentGateway.Charge(order.TotalAmount);
        Logger.Log($"Order {orderId} processed.");
        
        return true;
    }
}

🛠️ 3. MSTest 기반 테스트 환경 설정 (.NET Framework)

🚀 1) MSTest 설치

Visual Studio에서 다음과 같이 설정합니다:

  1. 새 프로젝트 생성 → .NET Framework → Unit Test Project(MSTest) 선택
  2. NuGet 패키지 설치

Install-Package MSTest.TestFramework
Install-Package MSTest.TestAdapter
Install-Package Moq

🚀 2) 첫 테스트 작성


using Microsoft.VisualStudio.TestTools.UnitTesting;

[TestClass]
public class OrderServiceTests
{
    [TestMethod]
    public void TestSample()
    {
        // Arrange
        int value1 = 1;
        int value2 = 1;

        // Act
        int result = value1 + value2;

        // Assert
        Assert.AreEqual(2, result);
    }
}

🚀 3) 테스트 실행

  • 테스트 탐색기 열기 → Ctrl + E, T
  • 테스트 실행 후 결과 확인 가능

🌟 4. 기존 레거시 코드 수정하기 (인터페이스 적용)

🔥 기존 코드 (테스트 불가 코드)


public static class Database
{
    public static Order GetOrderById(int orderId) 
    {
        // 실제 데이터베이스 접근 로직
    }
}

🔥 수정 코드 (인터페이스 적용)


public interface IDatabase
{
    Order GetOrderById(int orderId);
}

public class Database : IDatabase
{
    public Order GetOrderById(int orderId)
    {
        // 실제 데이터베이스 접근 로직
        return new Order { OrderId = orderId, TotalAmount = 100 };
    }
}

🚀 OrderService 수정 코드


public class OrderService
{
    private readonly IDatabase _database;

    public OrderService(IDatabase database)
    {
        _database = database;
    }

    public bool ProcessOrder(int orderId)
    {
        var order = _database.GetOrderById(orderId);
        if (order == null) return false;

        return true;
    }
}

🚀 5. Mocking 적용 및 테스트 작성


[TestMethod]
public void TestWithMock()
{
    // Arrange
    var mockDatabase = new Mock<IDatabase>();
    mockDatabase.Setup(db => db.GetOrderById(It.IsAny<int>()))
                .Returns(new Order { OrderId = 1, TotalAmount = 100 });

    var service = new OrderService(mockDatabase.Object);

    // Act
    var result = service.ProcessOrder(1);

    // Assert
    Assert.IsTrue(result);
}

🎯 결과

  • ✅ .NET Framework + MSTest 환경 설정 완료
  • ✅ 인터페이스 추출 및 의존성 주입 완료
  • ✅ Moq으로 Mocking 적용 완료
  • ✅ 첫 번째 테스트 성공

🚀 다음 편 예고

👉 다음 글에서는 외부 API 호출 및 Mocking 적용하는 예제를 다루겠습니다.
👉 통합 테스트와 단위 테스트의 차이점, 테스트 데이터베이스 설정 방법까지 상세히 설명하겠습니다.