ホームページ  >  記事  >  バックエンド開発  >  Golang 関数テストにおける分離の問題

Golang 関数テストにおける分離の問題

王林
王林オリジナル
2024-04-17 09:06:01698ブラウズ

Golang 関数のテストでは、異なるテスト間の干渉を避けるために分離が重要です。サブテーブルを使用してグローバル変数を分離するか、モック オブジェクトを使用して外部依存関係をシミュレートすることにより、分離の問題を解決します。具体的な手順は次のとおりです。 1. サブテーブル: 独立変数インスタンスを作成して干渉を回避します。 2. モック: モック依存関係のスタンドインを作成して外部依存関係を分離します。

Golang 函数测试中的隔离问题

Golang 関数テストにおける分離の問題

問題の理解

Golang In機能テスト、分離は非常に重要な概念です。分離しないとテストが相互に干渉し、信頼性の低い結果が得られる可能性があります。

問題の原因: グローバル変数と状態

グローバル変数と状態は、分離の問題の一般的な原因です。複数のテストが同じグローバル変数に対して実行される場合、それらのテストは互いに上書きされ、予期しない動作が発生する可能性があります。

解決策: サブテーブルとモックを使用する

分離の問題を解決するには、サブテーブルとモックという 2 つの一般的な戦略があります。

サブテーブル

サブテーブルは、テストごとに変数の独自のインスタンスを作成することでグローバル変数を分離します。これは、次の方法で実現できます。

package mypkg

// Global variable (not thread-safe)
var counter int

func Increment() int {
  counter++
  return counter
}
package mypkg_test

import (
  "testing"
)

func TestIncrement(t *testing.T) {
  // Create a sub-table for each test case
  t.Run("first call", func(t *testing.T) {
    // Initialize a new table-local counter
    counter := 0
    // Call the Increment function and assert the result
    result := mypkg.Increment()
    if result != 1 {
      t.Errorf("Expected 1, got %d", result)
    }
  })

  t.Run("second call", func(t *testing.T) {
    // Initialize a new table-local counter
    counter := 0
    // Call the Increment function and assert the result
    result := mypkg.Increment()
    if result != 2 {
      t.Errorf("Expected 2, got %d", result)
    }
  })
}

この例では、各テスト ケースに独自の counter 変数インスタンスがあるため、テスト ケース間の干渉が回避されます。

mock

モック オブジェクトはモック関数の代用であり、外部依存関係を分離するために使用できます。これは、外部サービスまたはデータベースに依存する機能をテストする場合に役立ちます。

package mypkg

type Database interface {
  // ...
}
package mypkg_test

import (
  "testing"

  "github.com/stretchr/testify/mock"
)

type DatabaseMock struct {
  mock.Mock
}

// ...

func TestMyFunction(t *testing.T) {
  // Create a mock database
  mockDB := &DatabaseMock{}

  // Setup mock expectations
  mockDB.On("Query", ...).Return(...)

  // Call the function under test with the mock database
  mypkg.MyFunction(mockDB)

  // Assert that the mock expectations were met
  mockDB.AssertExpectations(t)
}

この例では、DatabaseMockDatabase インターフェイスの代用であり、その動作をシミュレートして実際のデータベースへの依存を分離できます。

実際的なケース

電子メールを送信する次の関数を考えてみましょう:

package email

import (
  "github.com/go-mail/mail"
)

func SendEmail(smtpHost, smtpPort, senderEmail, senderPassword, recipientEmail, subject, body string) error {
  mail := mail.NewMessage()

  // ...

  smtpDialer := mail.NewDialer(smtpHost, smtpPort, senderEmail, senderPassword)
  return smtpDialer.DialAndSend(mail)
}

実際に電子メールを送信せずにこの関数をテストするには、次のようにします。 mail.Dialer:

package email_test

import (
  "testing"

  email "github.com/my-username/my-email-package"
  "github.com/stretchr/testify/mock"
)

type DialerMock struct {
  mock.Mock
}

func (d *DialerMock) DialAndSend(mail *mail.Message) error {
  d.Called(mail)
  return nil
}

func TestSendEmail(t *testing.T) {
  // Create a mock dialer
  mockDialer := &DialerMock{}

  // Setup mock expectations
  mockDialer.On("DialAndSend", ...).Return(nil)

  // Call the function under test with the mock dialer
  result := email.SendEmail("", "", "", "", "", "", "")

  // Assert that mock expectations were met
  mockDialer.AssertExpectations(t)

  // Assert the result of the function under test
  if result != nil {
    t.Errorf("Expected nil error but got %v", result)
  }
}
をシミュレートするモック オブジェクト

以上がGolang 関数テストにおける分離の問題の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。