0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Go】現在時刻に関する処理をインターフェース化してテストしやすくするサンプルコード(DI, 依存性注入)

Posted at

概要

  • 実務でよくありそうな現在時刻の取得処理をインターフェース化し、テストのしやすい構造にする
    • DIを使用してテストしやすいコードのサンプル
    • コンストラクタインジェクションを利用

サンプルコード

  • 現在時刻を生成する箇所をインターフェース化することで、テスト時にモックに差し替える事ができる
    • テスト実行時の現在時刻に依存することなくテストが可能になる
package main

import (
	"fmt"
	"time"
)

// 現在時刻を提供するインターフェース
type TimeProvider interface {
	Now() time.Time
}

type RealTimeProvider struct{}

func (tp *RealTimeProvider) Now() time.Time {
	return time.Now()
}

// ExpiryCheckerは期限切れをチェックする構造体
type ExpiryChecker struct {
	TimeProvider TimeProvider
}

func NewExpiryChecker(tp TimeProvider) *ExpiryChecker {
	return &ExpiryChecker{TimeProvider: tp}
}

func (ec *ExpiryChecker) IsExpired(deadline time.Time) bool {
	// time.Now()を直接呼び出すとテストの実行時刻に依存してしまう
	// そのため、TimeProviderインターフェースを通じて現在時刻を取得する
	// これにより、テスト時にモックを使って現在時刻を制御できる
	return ec.TimeProvider.Now().After(deadline)
}

func main() {
	checker := NewExpiryChecker(&RealTimeProvider{})

	// DBなどに保存されてる「期限」など
	deadline := time.Date(2025, 5, 9, 12, 0, 0, 0, time.Local)

	if checker.IsExpired(deadline) {
		fmt.Println("期限切れです")
	} else {
		fmt.Println("まだ有効です")
	}
}

テストコード

package main

import (
	"testing"
	"time"
)

// 現在時刻を提供するインターフェースのモック
type MockTimeProvider struct {
	FixedTime time.Time
}

func (m *MockTimeProvider) Now() time.Time {
	return m.FixedTime
}

func TestIsExpired(t *testing.T) {
	deadline := time.Date(2025, 5, 9, 12, 0, 0, 0, time.Local)

	tests := []struct {
		name     string
		now      time.Time
		expected bool
	}{
		{"期限前", time.Date(2025, 5, 9, 11, 0, 0, 0, time.Local), false},
		{"期限後", time.Date(2025, 5, 9, 13, 0, 0, 0, time.Local), true},
	}

	for _, tt := range tests {
		// モックを使って現在時刻を制御
		// これにより、テストの実行時刻に依存しない
		mock := &MockTimeProvider{FixedTime: tt.now}
		checker := NewExpiryChecker(mock)

		got := checker.IsExpired(deadline)
		if got != tt.expected {
			t.Errorf("[%s] expected %v, got %v", tt.name, tt.expected, got)
		}
	}
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?