>  기사  >  백엔드 개발  >  Golang 기능 테스트의 격리 문제

Golang 기능 테스트의 격리 문제

王林
王林원래의
2024-04-17 09:06:01690검색

Golang 기능 테스트에서는 서로 다른 테스트 간의 간섭을 피하기 위해 격리가 중요합니다. 하위 테이블을 사용하여 전역 변수를 격리하거나 모의 개체를 사용하여 외부 종속성을 시뮬레이션하여 격리 문제를 해결합니다. 구체적인 단계는 다음과 같습니다. 1. 하위 테이블: 간섭을 피하기 위해 독립 변수 인스턴스를 만듭니다. 2. 모의: 외부 종속성을 격리하기 위해 모의 종속성 대체 기능을 만듭니다.

Golang 函数测试中的隔离问题

Golang 기능 테스트의 격리 문제

문제 이해

Golang 기능 테스트에서 격리는 매우 중요한 개념입니다. 격리하지 않으면 테스트가 서로 간섭하여 신뢰할 수 없는 결과를 초래할 수 있습니다.

문제 원인: 전역 변수 및 상태

전역 변수 및 상태는 격리 문제의 일반적인 원인입니다. 여러 테스트가 동일한 전역 변수에서 작동하는 경우 서로 덮어쓰여 예기치 않은 동작이 발생할 수 있습니다.

해결책: 하위 테이블과 모의 테이블을 사용하세요

격리 문제를 해결하기 위해 하위 테이블과 모의 테이블이라는 두 가지 일반적인 전략이 있습니다.

Subtables

하위 테이블은 각 테스트에 대해 고유한 변수 인스턴스를 생성하여 전역 변수를 격리합니다. 이는 다음과 같이 달성할 수 있습니다:

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 변수의 자체 인스턴스가 있으므로 둘 사이의 간섭을 피할 수 있습니다. counter 变量实例,从而避免了它们之间的干扰。

mock

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)
}

要测试此函数而不实际发送电子邮件,我们可以使用 mock 对象来模拟 mail.Dialer

🎜mock🎜🎜🎜Mock 객체는 모의 함수의 대체 기능이며 외부 종속성을 격리하는 데 사용할 수 있습니다. 이는 외부 서비스나 데이터베이스에 의존하는 기능을 테스트하는 데 유용합니다. 🎜
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)
  }
}
rrreee🎜이 예에서 DatabaseMockDatabase 인터페이스의 대체 요소로, 실제 데이터베이스에 대한 종속성을 격리하기 위해 해당 동작을 시뮬레이션할 수 있습니다. 🎜🎜🎜실제 예🎜🎜🎜이메일을 보내는 다음 함수를 고려하세요. 🎜rrreee🎜실제로 이메일을 보내지 않고 이 기능을 테스트하려면 모의 개체를 사용하여 mail.Dialer를 시뮬레이션할 수 있습니다. 🎜아아아아

위 내용은 Golang 기능 테스트의 격리 문제의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.