PHpullh
학습 라이브러리/Go/목(Mock) 패턴

GO · 테스트

목(Mock) 패턴

인터페이스 기반 목 객체로 외부 의존성을 대체합니다. 직접 구현하거나 mockgen을 사용합니다.

테스트중급mocktestinginterfacedependency

핵심 설명

인터페이스 기반 목 객체로 외부 의존성을 대체합니다. 직접 구현하거나 mockgen을 사용합니다.

Go code

package main

import (
	"errors"
	"fmt"
	"testing"
)

type Mailer interface {
	Send(to, subject, body string) error
}

// 수동 목 구현
type MockMailer struct {
	SendFunc  func(to, subject, body string) error
	SendCalls []struct{ To, Subject, Body string }
}

func (m *MockMailer) Send(to, subject, body string) error {
	m.SendCalls = append(m.SendCalls, struct{ To, Subject, Body string }{to, subject, body})
	if m.SendFunc != nil { return m.SendFunc(to, subject, body) }
	return nil
}

type NotifyService struct{ mailer Mailer }

func (s *NotifyService) Welcome(email string) error {
	return s.mailer.Send(email, "환영합니다", "가입을 축하합니다!")
}

func TestWelcome(t *testing.T) {
	mock := &MockMailer{}
	svc := &NotifyService{mailer: mock}

	err := svc.Welcome("user@go.dev")
	if err != nil { t.Fatal(err) }

	if len(mock.SendCalls) != 1 { t.Fatal("Send 호출 1회 기대") }
	if mock.SendCalls[0].To != "user@go.dev" { t.Error("잘못된 수신자") }

	// 에러 시나리오
	mock.SendFunc = func(_, _, _ string) error { return errors.New("전송 실패") }
	err = svc.Welcome("fail@go.dev")
	if err == nil { t.Error("에러 기대") }
}

func main() {
	fmt.Println("인터페이스 기반 목 테스트 패턴")
}

학습 팁

목 구조체에 호출 기록을 저장하면 "올바른 인자로 호출되었는가"를 검증할 수 있습니다.

주의할 점

구체적 타입에 의존하면 목 교체가 불가능합니다. 항상 인터페이스에 의존하여 테스트 가능하게 만드세요.

자주 묻는 질문

목(Mock) 패턴란 무엇인가요?

인터페이스 기반 목 객체로 외부 의존성을 대체합니다. 직접 구현하거나 mockgen을 사용합니다.

목(Mock) 패턴 학습 시 주의할 점은 무엇인가요?

구체적 타입에 의존하면 목 교체가 불가능합니다. 항상 인터페이스에 의존하여 테스트 가능하게 만드세요.