Maison  >  Article  >  développement back-end  >  Problèmes d'isolement dans les tests de fonction Golang

Problèmes d'isolement dans les tests de fonction Golang

王林
王林original
2024-04-17 09:06:01690parcourir

Dans les tests de fonction Golang, l'isolement est crucial pour éviter les interférences entre les différents tests. Résolvez le problème d'isolation en isolant les variables globales à l'aide de sous-tableaux ou en simulant des dépendances externes à l'aide d'objets fictifs. Les étapes spécifiques sont les suivantes : 1. Sous-table : créer des instances de variables indépendantes pour éviter les interférences ; 2. Mock : créer des substituts de dépendance fictifs pour isoler les dépendances externes.

Golang 函数测试中的隔离问题

Problèmes d'isolement dans les tests de fonction Golang

Comprendre les problèmes

Dans les tests de fonction Golang, l'isolement est un concept très important. Sans isolement, les tests peuvent interférer les uns avec les autres, conduisant à des résultats peu fiables.

Source du problème : variables globales et état

Les variables globales et l'état sont une cause fréquente de problèmes d'isolement. Si plusieurs tests fonctionnent sur la même variable globale, ils peuvent s'écraser mutuellement, provoquant un comportement inattendu.

Solution : utiliser des sous-tables et des simulations

Pour résoudre le problème d'isolement, il existe deux stratégies courantes : les sous-tables et les simulations.

Sous-tables

Les sous-tables isolent les variables globales en créant leur propre instance de la variable pour chaque test. Ceci peut être réalisé par :

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

Dans cet exemple, chaque scénario de test a sa propre instance de la variable counter, évitant ainsi les interférences entre eux. 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🎜🎜🎜Les objets Mock remplacent les fonctions simulées et peuvent être utilisés pour isoler les dépendances externes. Ceci est utile pour tester des fonctions qui dépendent de services ou de bases de données externes. 🎜
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🎜Dans cet exemple, DatabaseMock est un remplaçant de l'interface Database, nous permettant de simuler son comportement pour isoler la dépendance à la base de données réelle. 🎜🎜🎜Exemple pratique🎜🎜🎜Considérez la fonction suivante, qui envoie un e-mail : 🎜rrreee🎜Pour tester cette fonction sans réellement envoyer d'e-mail, nous pouvons utiliser un objet fictif pour simuler mail.Dialer : 🎜rrreee

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn