From 5a4c422b7a0c05fc90c6dad21bbf7acb157f967f Mon Sep 17 00:00:00 2001 From: Michael Thomson Date: Thu, 13 Feb 2025 18:25:24 -0500 Subject: [PATCH] Added tests for full crud operations on psql --- .../todo/repository/postgres/postgres_test.go | 73 +++++++++++++++---- internal/todo/repository/repository.go | 4 + 2 files changed, 63 insertions(+), 14 deletions(-) diff --git a/internal/todo/repository/postgres/postgres_test.go b/internal/todo/repository/postgres/postgres_test.go index 325427e..67f9342 100644 --- a/internal/todo/repository/postgres/postgres_test.go +++ b/internal/todo/repository/postgres/postgres_test.go @@ -3,7 +3,7 @@ package postgres import ( "context" "database/sql" - "log" + "errors" "testing" "time" @@ -20,7 +20,8 @@ type TestDatabase struct { container testcontainers.Container } -func NewTestDatabase() *TestDatabase { +func NewTestDatabase(tb testing.TB) *TestDatabase { + tb.Helper() ctx := context.Background() // create container postgresContainer, err := postgres.Run(ctx, @@ -35,18 +36,18 @@ func NewTestDatabase() *TestDatabase { ) if err != nil { - log.Fatalf("Failed to create postgres container, %v\n", err) + tb.Fatalf("Failed to create postgres container, %v", err) } connectionString, err := postgresContainer.ConnectionString(ctx) if err != nil { - log.Fatal("Failed to get connection string") + tb.Fatalf("Failed to get connection string: %v", err) } // create db pool db, err := sql.Open("pgx", connectionString) if err != nil { - log.Fatal("Failed to open db pool") + tb.Fatalf("Failed to open db pool: %v", err) } migrate.Migrate(db) @@ -62,20 +63,64 @@ func (tdb *TestDatabase) TearDown() { _ = tdb.container.Terminate(context.Background()) } -func TestCreate(t *testing.T) { - tdb := NewTestDatabase() +func TestCRUD(t *testing.T) { + tdb := NewTestDatabase(t) defer tdb.TearDown() r := NewPostgresTodoRepository(tdb.Db) - todo := repository.TodoRow{Name: "clean dishes", Done: false} + t.Run("creates new todo", func(t *testing.T) { + want := repository.TodoRow{Id: 1, Name: "clean dishes", Done: false} + newTodo := repository.TodoRow{Name: "clean dishes", Done: false} + got, err := r.Create(newTodo) + AssertNoError(t, err) + AssertTodoRows(t, got, want) + }) - newTodo, err := r.Create(todo) + t.Run("gets todo", func(t *testing.T) { + want := repository.TodoRow{Id: 1, Name: "clean dishes", Done: false} + got, err := r.GetById(1) + AssertNoError(t, err) + AssertTodoRows(t, got, want) + }) - if err != nil { - t.Errorf("Expected no error, got %v", err) - } + t.Run("updates todo", func(t *testing.T) { + want := repository.TodoRow{Id: 1, Name: "clean dishes", Done: true} + err := r.Update(want) + AssertNoError(t, err) - if newTodo.Id != 1 || newTodo.Name != todo.Name || newTodo.Done != todo.Done { - t.Errorf("got %+v, want %+v", newTodo, todo) + got, err := r.GetById(1) + AssertNoError(t, err) + AssertTodoRows(t, got, want) + }) + + t.Run("deletes todo", func(t *testing.T) { + err := r.Delete(1) + AssertNoError(t, err) + + want := repository.ErrNotFound + _, got := r.GetById(1) + + AssertErrors(t, got, want) + }) +} + +func AssertErrors(t testing.TB, got, want error) { + t.Helper() + if !errors.Is(got, want) { + t.Errorf("got error: %v, want error: %v", want, got) + } +} + +func AssertNoError(t testing.TB, err error) { + t.Helper() + if err != nil { + t.Errorf("expected no error, got %v", err) + } +} + +func AssertTodoRows(t testing.TB, got, want repository.TodoRow) { + t.Helper() + if !got.Equal(want) { + t.Errorf("got %+v want %+v", got, want) } } diff --git a/internal/todo/repository/repository.go b/internal/todo/repository/repository.go index 35d40f0..b29223d 100644 --- a/internal/todo/repository/repository.go +++ b/internal/todo/repository/repository.go @@ -17,3 +17,7 @@ type TodoRow struct { func NewTodoRow(name string, done bool) TodoRow { return TodoRow{Name: name, Done: done} } + +func (t TodoRow) Equal(todo TodoRow) bool { + return t.Id == todo.Id && t.Name == todo.Name && t.Done == todo.Done +}