Vereinfachen Sie Go-Integrationstests mit gofacto: Eine leistungsstarke Fabrik für Scheindaten

PHPz
Freigeben: 2024-08-27 06:00:51
Original
904 Leute haben es durchsucht

Simplifying Go Integration Tests with gofacto: A Powerful Factory for Mock Data

Das Schreiben von Integrationstests mit Datenbanken ist für die Entwicklung von Webanwendungen von entscheidender Bedeutung, da es das Vertrauen in unseren Code stärkt und sicherstellt, dass unsere Anwendung wie erwartet funktioniert. Allerdings kann die Vorbereitung von Scheindaten für diese Tests eine Herausforderung darstellen, insbesondere in Go, wo es für diese Aufgabe keinen integrierten Ansatz oder keine Standardbibliothek gibt. In diesem Artikel wird die Gofacto-Bibliothek vorgestellt, die den Prozess der Erstellung von Scheindaten und deren Einfügen in Datenbanken für Go-Integrationstests vereinfacht.

 

Was heißt gofacto?

gofacto ist eine Go-Bibliothek, die die Erstellung und das Einfügen von Scheindaten in Datenbanken vereinfacht. Es bietet einen intuitiven Ansatz zum Definieren von Datenschemata und zum effizienten Umgang mit Datenbankeinfügungen. Mit gofacto können Entwickler Testdaten schnell vorbereiten, ohne umfangreiche Boilerplate-Codes schreiben zu müssen, sodass sie sich auf das Schreiben aussagekräftiger Tests konzentrieren können.

 

Vor der Verwendung von Gofacto

Sehen wir uns an, was wir normalerweise tun, wenn wir Integrationstests mit Datenbanken in Go schreiben. Angenommen, wir haben eine Tabelle mit dem Namen „Benutzer“ in der Datenbank und sie weist das folgende Schema auf:

CREATE TABLE users (
    id INT PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) NOT NULL
);
Nach dem Login kopieren

Angenommen, wir möchten eine Funktion namens getUserByID testen, die einen Benutzer anhand seiner ID aus der Benutzertabelle abruft. Um diese Funktion zu testen, müssen wir vor dem Testen dieser Funktion einige Scheindaten in der Datenbank vorbereiten. So machen wir es normalerweise:

type User struct {
    ID      int
    Gender  string
    Name    string
    Email   string
}

// build and insert mock user
mockUser := User{
    ID:     1,
    Gender: "male",
    Name:   "Alice",
    Email:  "aaa@gmail.com",
}
err := insertToDB(mockUser)

// action
result, err := getUserByID(mockUser.ID)

// assertion
// ...
Nach dem Login kopieren

insertToDB ist eine Funktion, die Scheindaten in die Datenbank einfügt. Es kann sehr komplex sein, wenn wir unformatierte SQL-Abfragen verwenden.

Dieser Ansatz erscheint machbar, da das Schema einfach ist und wir uns nur mit einer Tabelle befassen.

Sehen wir uns den Fall an, wenn wir uns mit zwei Tabellen, Benutzern und Beiträgen, befassen. Jeder Benutzer kann mehrere Beiträge haben und die Beziehung zwischen den Tabellen wird durch das Feld „user_id“ in der Beitragstabelle hergestellt.

CREATE TABLE posts (
    id INT PRIMARY KEY,
    user_id INT NOT NULL,
    title VARCHAR(255) NOT NULL,
    content TEXT NOT NULL,
    FOREIGN KEY (user_id) REFERENCES users(id)
);
Nach dem Login kopieren

Angenommen, wir möchten eine Funktion namens getPostsByUserID testen, die alle Beiträge nach der ID eines Benutzers aus der Beitragstabelle abruft.

type Post struct {
  ID      int
  UserID  int
  Title   string
  Content string
}

// build and insert mock user
mockUser := User{
    ID:     1,
    Gender: "male",
    Name:   "Alice",
    Email:  "aaa@gmail.com",
}
err := insertToDB(mockUser)

// build and insert mock post
mockPost1 := Post{
  ID:      1,
  UserID:  mockUser.ID, // manually set the foreign key
  Title:   "Post 1",
  Content: "Content 1",
}
err = insertToDB(mockPost1)

// build and insert mock post
mockPost2 := Post{
  ID:      2,
  UserID:  mockUser.ID, // manually set the foreign key
  Title:   "Post 2",
  Content: "Content 2",
}
err = insertToDB(mockPost2)

// action
result, err := getPostsByUserID(mockUser.ID)

// assertion
// ...
Nach dem Login kopieren

Wir erstellen zunächst einen Benutzer und erstellen dann zwei Beiträge für diesen Benutzer. Im Vergleich zum vorherigen Beispiel wird es komplexer, da wir uns mit zwei Tabellen befassen und die Beziehung zwischen ihnen herstellen.

Was ist, wenn wir mehrere Beiträge mit unterschiedlichen Benutzern erstellen möchten?
Wir müssen für jeden Beitrag einen Benutzer erstellen und dafür ist mehr Code erforderlich.

// build and insert mock user
mockUser1 := User{
  ID:    1,
  Gender: "male",
  Name:  "Alice",
  Email: "aaa@gmail.com",
}
err := insertToDB(mockUser1)

// build and insert mock user
mockUser2 := User{
  ID:  2,
  Gender: "female",
  Name:  "Bob",
  Email: "bbb@gmail.com",
}
err = insertToDB(mockUser2)

// build and insert mock post
mockPost1 := Post{
  ID:      1,
  UserID:  mockUser1.ID, // manually set the foreign key
  Title:   "Post 1",
  Content: "Content 1",
}
err = insertToDB(mockPost1)

// build and insert mock post
mockPost2 := Post{
  ID:      2,
  UserID:  mockUser2.ID, // manually set the foreign key
  Title:   "Post 2",
  Content: "Content 2",
}
err = insertToDB(mockPost2)

// action
result, err := getPostsByUserID(mockUser1.ID)

// assertion
// ...
Nach dem Login kopieren

Es wird immer komplexer und fehleranfälliger, wenn wir mehrere Scheindaten mit unterschiedlichen Benutzern und Beiträgen erstellen müssen.

Beachten Sie auch, dass wir nur zu Demonstrationszwecken ein einfaches Schema verwenden. Der Code wird in den realen Anwendungen komplexer sein.

 

Was sind die Probleme?

In den obigen Beispielen gibt es einige Probleme:

  • Schreiben Sie viel Boilerplate-Code, um Scheindaten in der Datenbank vorzubereiten
    • Manchmal ist uns der Wert der Felder egal, wir müssen nur sicherstellen, dass in jedem Feld ein korrekter Wert vorhanden ist.
  • Den Wert der ID in den Scheindaten fest codieren
    • Es empfiehlt sich nicht, den Wert der ID in den Scheindaten fest zu codieren, da die ID normalerweise automatisch inkrementiert wird die Datenbank.
  • Manuelles Herstellen von Beziehungen zwischen Tabellen
    • Dies macht den Testcode umständlich und fehleranfällig, insbesondere beim Erstellen von Scheindaten mit mehreren zugehörigen Tabellen.

 

Verwendung von Gofacto

Jetzt wollen wir sehen, wie die Gofacto-Bibliothek uns helfen kann, die oben genannten Probleme zu lösen und den gesamten Prozess zu vereinfachen.

Sehen wir uns das erste Beispiel mit der Benutzertabelle an.

// initialize a factory with User struct (also use `WithDB` to pass the database connection)
f := gofacto.New(User{}).WithDB(db)

// build and insert mock user
mockUser, err := f.Build(ctx).Insert()

// action
result, err := getUserByID(mockUser.ID)

// assertion
// ...
Nach dem Login kopieren

Um gofacto zu verwenden, verwenden wir zunächst die Funktion „Neu“, um eine neue Factory mit „Benutzer“ zu initialisieren. Da wir Daten in die Datenbank einfügen müssen, verwenden wir WithDB, um die Datenbankverbindung an die Fabrik weiterzuleiten.
Dann verwenden wir die Build-Funktion, um die Scheindaten zu erstellen. Die Funktion „Einfügen“ fügt die Scheindaten in die Datenbank ein und gibt die Scheindaten zurück, die mit der automatisch inkrementierten ID in die Datenbank eingefügt wurden.

Beachten Sie, dass alle Felder der Scheindaten standardmäßig zufällig generiert werden. In diesem Fall ist das in Ordnung, da uns der Wert der Felder egal ist.

Falls wir den Wert der Felder angeben möchten, können wir die Funktion „Überschreiben“ verwenden, um den Wert der Felder festzulegen.

mockUser, err := f.Build(ctx).Overwrite(User{Gender: "male"}).Insert()
// mockUser.Gender == "male"
Nach dem Login kopieren

Bei Verwendung der Überschreibfunktion müssen wir nur die Felder angeben, die wir überschreiben möchten. Die anderen Felder werden wie gewohnt zufällig generiert.

Sehen wir uns den Fall an, in dem wir mehrere Beiträge mit einem Benutzer erstellen möchten.
Damit gofacto die Beziehung zwischen den Tabellen kennt, müssen wir die richtigen Tags in der Struktur definieren.

type Post struct {
    ID      int
    UserID  int       `gofacto:"foreignKey,struct:User"`
    Title   string
    Content string
}
Nach dem Login kopieren

The tag tells gofacto that the UserID field is a foreign key that references the ID field of the User struct.

Now, we can create multiple posts with one user easily.

mockUser := User{}
mockPosts, err := f.BuildList(ctx, 2).WithOne(&mockUser).Insert() // must pass pointer to the struct to `WithOne`
// mockPosts[0].UserID == mockUser.ID
// mockPosts[1].UserID == mockUser.ID

// action
result, err := getPostsByUserID(mockUser.ID)

// assertion
// ...
Nach dem Login kopieren

In order to create multiple posts, we use BuildList function with the number of posts that we want to create. Then, we use WithOne function to specify that all the posts belong to one user. The Insert function returns a list of posts that have been inserted into the database with the auto-incremented ID.

gofacto library makes sure all the fields are correctly set randomly, and the relationship between the tables is correctly established.

Let's see the case where we want to create multiple posts with different users.

mockUser1 := User{}
mockUser2 := User{}
mockPosts, err := f.BuildList(ctx, 2).WithMany([]interface{}{&mockUser1, &mockUser2}).Insert()
// mockPosts[0].UserID == mockUser1.ID
// mockPosts[1].UserID == mockUser2.ID

// action
result, err := getPostsByUserID(mockUser1.ID)

// assertion
// ...
Nach dem Login kopieren

We use WithMany function to specify that each post is associated with a different user.

 

Summary

We've seen how gofacto simplifies writing integration tests with databases in Go. It reduces boilerplate code and makes it easier to prepare mock data with multiple tables and establish relationships between them. Most importantly, gofacto abstracts away the complexity of preparing mock data, allowing developers to focus on writing meaningful tests. To start using gofacto in your Go projects, visit the GitHub repository for installation instructions and more detailed documentation.

 

Feedback and Further Development

As a new library developer, I'd love to hear your thoughts on gofacto! Any feedback, advice or criticism is appreciated. If you use it in your Go projects, please share your experience. Found a bug or have an idea? Open an issue on the gofacto GitHub repo. Want to contribute code? Pull requests are welcome! Your feedback and contributions will help improve gofacto and benefit the Go community. Thanks for checking it out!

Das obige ist der detaillierte Inhalt vonVereinfachen Sie Go-Integrationstests mit gofacto: Eine leistungsstarke Fabrik für Scheindaten. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!