1+ package crud
2+
3+ import (
4+ "context"
5+ "testing"
6+ "time"
7+ )
8+
9+ type TestEntity struct {
10+ ID int64 `json:"id"`
11+ Name string `json:"name"`
12+ CreatedAt time.Time `json:"created_at"`
13+ UpdatedAt time.Time `json:"updated_at"`
14+ }
15+
16+ func (e TestEntity ) GetID () int64 {
17+ return e .ID
18+ }
19+
20+ func (e TestEntity ) GetName () string {
21+ return e .Name
22+ }
23+
24+ func (e TestEntity ) GetCreatedAt () time.Time {
25+ return e .CreatedAt
26+ }
27+
28+ func (e TestEntity ) GetUpdatedAt () time.Time {
29+ return e .UpdatedAt
30+ }
31+
32+ func TestCRUDInterface (t * testing.T ) {
33+ ctx := context .Background ()
34+
35+ t .Run ("Create" , func (t * testing.T ) {
36+ manager := & testCRUDManager {}
37+
38+ entity , err := manager .Create (ctx , "test-entity" )
39+ if err != nil {
40+ t .Fatalf ("Create failed: %v" , err )
41+ }
42+
43+ if entity .GetName () != "test-entity" {
44+ t .Errorf ("expected name 'test-entity', got %s" , entity .GetName ())
45+ }
46+
47+ if entity .GetID () == 0 {
48+ t .Error ("expected ID to be set" )
49+ }
50+
51+ if entity .GetCreatedAt ().IsZero () {
52+ t .Error ("expected CreatedAt to be set" )
53+ }
54+ })
55+
56+ t .Run ("Read" , func (t * testing.T ) {
57+ manager := & testCRUDManager {}
58+
59+ // Create entity first
60+ created , err := manager .Create (ctx , "test-read" )
61+ if err != nil {
62+ t .Fatalf ("Create failed: %v" , err )
63+ }
64+
65+ // Read it back
66+ entity , err := manager .Read (ctx , created .GetID ())
67+ if err != nil {
68+ t .Fatalf ("Read failed: %v" , err )
69+ }
70+
71+ if entity .GetID () != created .GetID () {
72+ t .Errorf ("expected ID %d, got %d" , created .GetID (), entity .GetID ())
73+ }
74+
75+ if entity .GetName () != "test-read" {
76+ t .Errorf ("expected name 'test-read', got %s" , entity .GetName ())
77+ }
78+ })
79+
80+ t .Run ("Update" , func (t * testing.T ) {
81+ manager := & testCRUDManager {}
82+
83+ // Create entity first
84+ created , err := manager .Create (ctx , "original-name" )
85+ if err != nil {
86+ t .Fatalf ("Create failed: %v" , err )
87+ }
88+
89+ // Update it
90+ updated , err := manager .Update (ctx , created .GetID (), "updated-name" )
91+ if err != nil {
92+ t .Fatalf ("Update failed: %v" , err )
93+ }
94+
95+ if updated .GetName () != "updated-name" {
96+ t .Errorf ("expected name 'updated-name', got %s" , updated .GetName ())
97+ }
98+
99+ if updated .GetUpdatedAt ().Before (created .GetUpdatedAt ()) {
100+ t .Error ("expected UpdatedAt to be updated" )
101+ }
102+ })
103+
104+ t .Run ("Delete" , func (t * testing.T ) {
105+ manager := & testCRUDManager {}
106+
107+ // Create entity first
108+ created , err := manager .Create (ctx , "to-delete" )
109+ if err != nil {
110+ t .Fatalf ("Create failed: %v" , err )
111+ }
112+
113+ // Delete it
114+ err = manager .Delete (ctx , created .GetID ())
115+ if err != nil {
116+ t .Fatalf ("Delete failed: %v" , err )
117+ }
118+
119+ // Verify it's gone
120+ _ , err = manager .Read (ctx , created .GetID ())
121+ if err == nil {
122+ t .Error ("expected Read to fail after Delete" )
123+ }
124+ })
125+
126+ t .Run ("List" , func (t * testing.T ) {
127+ manager := & testCRUDManager {}
128+
129+ // Create some entities
130+ names := []string {"entity1" , "entity2" , "entity3" }
131+ for _ , name := range names {
132+ _ , err := manager .Create (ctx , name )
133+ if err != nil {
134+ t .Fatalf ("Create failed: %v" , err )
135+ }
136+ }
137+
138+ // List them
139+ entities , err := manager .List (ctx )
140+ if err != nil {
141+ t .Fatalf ("List failed: %v" , err )
142+ }
143+
144+ if len (entities ) < len (names ) {
145+ t .Errorf ("expected at least %d entities, got %d" , len (names ), len (entities ))
146+ }
147+ })
148+ }
149+
150+ func TestCRUDValidation (t * testing.T ) {
151+ ctx := context .Background ()
152+ manager := & testCRUDManager {}
153+
154+ t .Run ("Create with empty name" , func (t * testing.T ) {
155+ _ , err := manager .Create (ctx , "" )
156+ if err == nil {
157+ t .Error ("expected Create with empty name to fail" )
158+ }
159+ })
160+
161+ t .Run ("Read non-existent entity" , func (t * testing.T ) {
162+ _ , err := manager .Read (ctx , 99999 )
163+ if err == nil {
164+ t .Error ("expected Read of non-existent entity to fail" )
165+ }
166+ })
167+
168+ t .Run ("Update non-existent entity" , func (t * testing.T ) {
169+ _ , err := manager .Update (ctx , 99999 , "new-name" )
170+ if err == nil {
171+ t .Error ("expected Update of non-existent entity to fail" )
172+ }
173+ })
174+
175+ t .Run ("Delete non-existent entity" , func (t * testing.T ) {
176+ err := manager .Delete (ctx , 99999 )
177+ if err == nil {
178+ t .Error ("expected Delete of non-existent entity to fail" )
179+ }
180+ })
181+ }
182+
183+ // Mock implementation for testing
184+ type testCRUDManager struct {
185+ entities map [int64 ]TestEntity
186+ nextID int64
187+ }
188+
189+ func (m * testCRUDManager ) Create (ctx context.Context , name string ) (TestEntity , error ) {
190+ if m .entities == nil {
191+ m .entities = make (map [int64 ]TestEntity )
192+ m .nextID = 1
193+ }
194+
195+ if name == "" {
196+ return TestEntity {}, ErrInvalidInput
197+ }
198+
199+ now := time .Now ()
200+ entity := TestEntity {
201+ ID : m .nextID ,
202+ Name : name ,
203+ CreatedAt : now ,
204+ UpdatedAt : now ,
205+ }
206+
207+ m .entities [m .nextID ] = entity
208+ m .nextID ++
209+
210+ return entity , nil
211+ }
212+
213+ func (m * testCRUDManager ) Read (ctx context.Context , id int64 ) (TestEntity , error ) {
214+ if m .entities == nil {
215+ return TestEntity {}, ErrNotFound
216+ }
217+
218+ entity , exists := m .entities [id ]
219+ if ! exists {
220+ return TestEntity {}, ErrNotFound
221+ }
222+
223+ return entity , nil
224+ }
225+
226+ func (m * testCRUDManager ) Update (ctx context.Context , id int64 , name string ) (TestEntity , error ) {
227+ if m .entities == nil {
228+ return TestEntity {}, ErrNotFound
229+ }
230+
231+ entity , exists := m .entities [id ]
232+ if ! exists {
233+ return TestEntity {}, ErrNotFound
234+ }
235+
236+ if name == "" {
237+ return TestEntity {}, ErrInvalidInput
238+ }
239+
240+ entity .Name = name
241+ entity .UpdatedAt = time .Now ()
242+ m .entities [id ] = entity
243+
244+ return entity , nil
245+ }
246+
247+ func (m * testCRUDManager ) Delete (ctx context.Context , id int64 ) error {
248+ if m .entities == nil {
249+ return ErrNotFound
250+ }
251+
252+ _ , exists := m .entities [id ]
253+ if ! exists {
254+ return ErrNotFound
255+ }
256+
257+ delete (m .entities , id )
258+ return nil
259+ }
260+
261+ func (m * testCRUDManager ) List (ctx context.Context ) ([]TestEntity , error ) {
262+ if m .entities == nil {
263+ return []TestEntity {}, nil
264+ }
265+
266+ entities := make ([]TestEntity , 0 , len (m .entities ))
267+ for _ , entity := range m .entities {
268+ entities = append (entities , entity )
269+ }
270+
271+ return entities , nil
272+ }
0 commit comments