todo service tests

This commit is contained in:
Michael Thomson 2025-02-07 22:05:05 -05:00
parent a71e09367c
commit 6175abee25
No known key found for this signature in database
GPG Key ID: 8EFECCD347C72F7D
5 changed files with 130 additions and 17 deletions

View File

@ -35,5 +35,5 @@ func main() {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
fmt.Printf("ID of created todo: %d", newTodo.Id) fmt.Printf("ID of created todo: %d\n", newTodo.Id)
} }

View File

@ -5,20 +5,20 @@ import (
) )
type InMemoryTodoRepository struct { type InMemoryTodoRepository struct {
db map[int64]repository.TodoRow Db map[int64]repository.TodoRow
id int64 id int64
} }
func NewInMemoryTodoRepository() InMemoryTodoRepository { func NewInMemoryTodoRepository() InMemoryTodoRepository {
return InMemoryTodoRepository{ return InMemoryTodoRepository{
db: make(map[int64]repository.TodoRow), Db: make(map[int64]repository.TodoRow),
id: 1, id: 1,
} }
} }
func (r *InMemoryTodoRepository) GetById(id int64) (repository.TodoRow, error) { func (r *InMemoryTodoRepository) GetById(id int64) (repository.TodoRow, error) {
todo, found := r.db[id] todo, found := r.Db[id]
if !found { if !found {
return todo, repository.ErrNotFound return todo, repository.ErrNotFound
@ -29,32 +29,32 @@ func (r *InMemoryTodoRepository) GetById(id int64) (repository.TodoRow, error) {
func (r *InMemoryTodoRepository) Create(todo repository.TodoRow) (repository.TodoRow, error) { func (r *InMemoryTodoRepository) Create(todo repository.TodoRow) (repository.TodoRow, error) {
todo.Id = r.id todo.Id = r.id
r.db[r.id] = todo r.Db[r.id] = todo
r.id++ r.id++
return todo, nil return todo, nil
} }
func (r *InMemoryTodoRepository) Update(todo repository.TodoRow) error { func (r *InMemoryTodoRepository) Update(todo repository.TodoRow) error {
_, found := r.db[todo.Id] _, found := r.Db[todo.Id]
if !found { if !found {
return repository.ErrNotFound return repository.ErrNotFound
} }
r.db[todo.Id] = todo r.Db[todo.Id] = todo
return nil return nil
} }
func (r *InMemoryTodoRepository) Delete(id int64) error { func (r *InMemoryTodoRepository) Delete(id int64) error {
_, found := r.db[id] _, found := r.Db[id]
if !found { if !found {
return repository.ErrNotFound return repository.ErrNotFound
} }
delete(r.db, id) delete(r.Db, id)
return nil return nil
} }

View File

@ -14,8 +14,8 @@ type TodoRow struct {
Done bool Done bool
} }
func NewTodoDbModel(name string, done bool) *TodoRow { func NewTodoRow(name string, done bool) TodoRow {
return &TodoRow{Name: name, Done: done} return TodoRow{Name: name, Done: done}
} }
type TodoRepository interface { type TodoRepository interface {

View File

@ -1,9 +1,17 @@
package service package service
import "gitea.michaelthomson.dev/mthomson/habits/internal/todo/repository" import (
"errors"
"gitea.michaelthomson.dev/mthomson/habits/internal/todo/repository"
)
var (
ErrNotFound error = errors.New("Todo cannot be found")
)
type Todo struct { type Todo struct {
Id int64 Id int64
Name string Name string
Done bool Done bool
} }
@ -20,6 +28,10 @@ func TodoRowFromTodo(todo Todo) repository.TodoRow {
return repository.TodoRow{Id: todo.Id, Name: todo.Name, Done: todo.Done} return repository.TodoRow{Id: todo.Id, Name: todo.Name, Done: todo.Done}
} }
func (t Todo) Equal(todo Todo) bool {
return t.Id == todo.Id && t.Name == todo.Name && t.Done == todo.Done
}
type TodoGetter interface { type TodoGetter interface {
GetTodo(id int64) (Todo, error) GetTodo(id int64) (Todo, error)
} }
@ -48,6 +60,10 @@ func (s *TodoService) GetTodo(id int64) (Todo, error) {
todo, err := s.repo.GetById(id) todo, err := s.repo.GetById(id)
if err != nil { if err != nil {
if err == repository.ErrNotFound {
return Todo{}, ErrNotFound
}
return Todo{}, err return Todo{}, err
} }
@ -67,7 +83,11 @@ func (s *TodoService) CreateTodo(todo Todo) (Todo, error) {
} }
func (s *TodoService) DeleteTodo(id int64) error { func (s *TodoService) DeleteTodo(id int64) error {
err := s.repo.Delete(id); err := s.repo.Delete(id)
if err == repository.ErrNotFound {
return ErrNotFound
}
return err return err
} }
@ -77,5 +97,9 @@ func (s *TodoService) UpdateTodo(todo Todo) error {
err := s.repo.Update(todoRow) err := s.repo.Update(todoRow)
if err == repository.ErrNotFound {
return ErrNotFound
}
return err return err
} }

View File

@ -3,6 +3,7 @@ package service_test
import ( import (
"testing" "testing"
"gitea.michaelthomson.dev/mthomson/habits/internal/todo/repository"
"gitea.michaelthomson.dev/mthomson/habits/internal/todo/repository/inmemory" "gitea.michaelthomson.dev/mthomson/habits/internal/todo/repository/inmemory"
"gitea.michaelthomson.dev/mthomson/habits/internal/todo/service" "gitea.michaelthomson.dev/mthomson/habits/internal/todo/service"
) )
@ -17,8 +18,96 @@ func TestCreateTodo(t *testing.T) {
_, err := todoService.CreateTodo(todo) _, err := todoService.CreateTodo(todo)
if err != nil { AssertNoError(t, err)
t.Error(err)
}
}) })
} }
func TestGetTodo(t *testing.T) {
todoRepository := inmemory.NewInMemoryTodoRepository()
todoRepository.Db[1] = repository.TodoRow{Id: 1, Name: "clean dishes", Done: false}
todoService := service.NewTodoService(&todoRepository)
t.Run("Get exisiting todo", func(t *testing.T) {
_, err := todoService.GetTodo(1)
AssertNoError(t, err)
})
t.Run("Get non-existant todo", func(t *testing.T) {
_, err := todoService.GetTodo(2)
AssertErrors(t, err, service.ErrNotFound)
})
}
func TestDeleteTodo(t *testing.T) {
todoRepository := inmemory.NewInMemoryTodoRepository()
todoRepository.Db[1] = repository.TodoRow{Id: 1, Name: "clean dishes", Done: false}
todoService := service.NewTodoService(&todoRepository)
t.Run("Delete exisiting todo", func(t *testing.T) {
err := todoService.DeleteTodo(1)
AssertNoError(t, err)
})
t.Run("Delete non-existant todo", func(t *testing.T) {
err := todoService.DeleteTodo(1)
AssertErrors(t, err, service.ErrNotFound)
})
}
func TestUpdateTodo(t *testing.T) {
todoRepository := inmemory.NewInMemoryTodoRepository()
todoRepository.Db[1] = repository.TodoRow{Id: 1, Name: "clean dishes", Done: false}
todoService := service.NewTodoService(&todoRepository)
t.Run("Update exisiting todo", func(t *testing.T) {
todo := service.Todo{1, "clean dishes", true}
err := todoService.UpdateTodo(todo)
AssertNoError(t, err)
newTodo, err := todoService.GetTodo(1)
AssertNoError(t, err)
AssertTodos(t, newTodo, todo)
})
t.Run("Update non-existant todo", func(t *testing.T) {
todo := service.Todo{2, "clean dishes", true}
err := todoService.UpdateTodo(todo)
AssertErrors(t, err, service.ErrNotFound)
})
}
func AssertErrors(t testing.TB, got, want error) {
t.Helper()
if 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 AssertTodos(t testing.TB, got, want service.Todo) {
if !got.Equal(want) {
t.Errorf("got %+v want %+v", got, want)
}
}