github.com/joao-fontenele/go-url-shortener@v1.3.4/pkg/shortener/repository_test.go (about) 1 package shortener_test 2 3 import ( 4 "context" 5 "errors" 6 "testing" 7 "time" 8 9 "github.com/google/go-cmp/cmp" 10 "github.com/joao-fontenele/go-url-shortener/pkg/mocks" 11 "github.com/joao-fontenele/go-url-shortener/pkg/shortener" 12 ) 13 14 type findFn func(ctx context.Context, slug string) (*shortener.Link, error) 15 16 func TestFind(t *testing.T) { 17 sampleLink := &shortener.Link{ 18 Slug: "aaaaa", 19 URL: "htttps://wwww.google.com", 20 CreatedAt: time.Date(2020, 5, 1, 0, 0, 0, 0, time.UTC), 21 } 22 23 hitFind := func(ctx context.Context, slug string) (*shortener.Link, error) { 24 return sampleLink, nil 25 } 26 27 missFind := func(ctx context.Context, slug string) (*shortener.Link, error) { 28 return nil, shortener.ErrLinkNotFound 29 } 30 31 t.Run("CacheHit", func(t *testing.T) { 32 db := &mocks.FakeLinkDao{FindFn: hitFind} 33 cache := &mocks.FakeLinkDao{FindFn: hitFind} 34 35 r := shortener.NewLinkRepository(db, cache) 36 37 link, err := r.Find(context.Background(), "dontcare") 38 39 if err != nil { 40 t.Errorf("Unexpected error calling repository Find: %v", err) 41 } 42 43 if db.FindCalled { 44 t.Error("Expected db find to not have been called") 45 } 46 47 if !cache.FindCalled { 48 t.Error("Expected cache find to have been called") 49 } 50 51 if diff := cmp.Diff(sampleLink, link); diff != "" { 52 t.Errorf("Found link different from expected (-want +got):\n%s", diff) 53 } 54 }) 55 56 t.Run("CacheMissDbMiss", func(t *testing.T) { 57 db := &mocks.FakeLinkDao{FindFn: missFind} 58 cache := &mocks.FakeLinkDao{FindFn: missFind} 59 60 r := shortener.NewLinkRepository(db, cache) 61 62 link, err := r.Find(context.Background(), "dontcare") 63 64 if link != nil { 65 t.Errorf("Expected link to be nil, but got: %v", link) 66 } 67 68 if !errors.Is(err, shortener.ErrLinkNotFound) { 69 t.Errorf("Expected error to be ErrLinkNotFound, but got: %v", err) 70 } 71 72 if !db.FindCalled { 73 t.Error("Expected db find to have been called") 74 } 75 76 if !cache.FindCalled { 77 t.Error("Expected cache find to have been called") 78 } 79 }) 80 81 t.Run("CacheMissDbHit", func(t *testing.T) { 82 db := &mocks.FakeLinkDao{FindFn: hitFind} 83 cache := &mocks.FakeLinkDao{FindFn: missFind} 84 85 r := shortener.NewLinkRepository(db, cache) 86 87 link, err := r.Find(context.Background(), "dontcare") 88 89 if err != nil { 90 t.Errorf("Unexpected error calling repository Find: %v", err) 91 } 92 93 if !db.FindCalled { 94 t.Error("Expected db find to not have been called") 95 } 96 97 if !cache.FindCalled { 98 t.Error("Expected cache find to have been called") 99 } 100 101 if diff := cmp.Diff(sampleLink, link); diff != "" { 102 t.Errorf("Found link different from expected (-want +got):\n%s", diff) 103 } 104 }) 105 } 106 107 func TestInsert(t *testing.T) { 108 sampleLink := &shortener.Link{ 109 URL: "https://www.google.com/?search=Google", 110 Slug: "aaaaa", 111 CreatedAt: time.Now(), 112 } 113 okInsert := func(ctx context.Context, l *shortener.Link) (*shortener.Link, error) { 114 return sampleLink, nil 115 } 116 117 failInsert := func(ctx context.Context, l *shortener.Link) (*shortener.Link, error) { 118 return nil, errors.New("UnexpectedErr") 119 } 120 121 t.Run("InvalidLink", func(t *testing.T) { 122 db := &mocks.FakeLinkDao{} 123 cache := &mocks.FakeLinkDao{} 124 125 r := shortener.NewLinkRepository(db, cache) 126 127 invalid := &shortener.Link{} 128 _, err := r.Insert(context.Background(), invalid) 129 130 if !errors.Is(err, shortener.ErrInvalidLink) { 131 t.Errorf("Expected err to be %v, but got %v", shortener.ErrInvalidLink, err) 132 } 133 }) 134 135 t.Run("DbFail", func(t *testing.T) { 136 db := &mocks.FakeLinkDao{InsertFn: failInsert} 137 cache := &mocks.FakeLinkDao{InsertFn: okInsert} 138 139 r := shortener.NewLinkRepository(db, cache) 140 141 link, err := r.Insert(context.Background(), sampleLink) 142 143 if err == nil { 144 t.Error("Expected Insert to fail, but got err: nil") 145 } 146 147 if cache.InsertCalled { 148 t.Error("Expected cache to not have been called") 149 } 150 151 if diff := cmp.Diff(sampleLink, link); diff != "" { 152 t.Errorf("Inserted link different from expected (-want +got):\n%s", diff) 153 } 154 }) 155 156 t.Run("DbOK", func(t *testing.T) { 157 db := &mocks.FakeLinkDao{InsertFn: okInsert} 158 cache := &mocks.FakeLinkDao{InsertFn: okInsert} 159 160 r := shortener.NewLinkRepository(db, cache) 161 162 link, err := r.Insert(context.Background(), sampleLink) 163 164 if err != nil { 165 t.Errorf("Unexpected error inserting link: %v", err) 166 } 167 168 if !cache.InsertCalled { 169 t.Error("Expected cache to have been called") 170 } 171 172 if diff := cmp.Diff(sampleLink, link); diff != "" { 173 t.Errorf("Inserted link different from expected (-want +got):\n%s", diff) 174 } 175 }) 176 } 177 178 func TestDelete(t *testing.T) { 179 slug := "b4zoo" 180 okDelete := func(ctx context.Context, slug string) error { 181 return nil 182 } 183 184 failDelete := func(ctx context.Context, slug string) error { 185 return shortener.ErrInvalidLink 186 } 187 188 t.Run("DbFail", func(t *testing.T) { 189 db := &mocks.FakeLinkDao{DeleteFn: failDelete} 190 cache := &mocks.FakeLinkDao{DeleteFn: okDelete} 191 192 r := shortener.NewLinkRepository(db, cache) 193 194 err := r.Delete(context.Background(), slug) 195 196 if err == nil { 197 t.Error("Expected Insert to fail, but got err: nil") 198 } 199 200 if cache.DeleteCalled { 201 t.Error("Expected cache to not have been called") 202 } 203 }) 204 205 t.Run("DbOK", func(t *testing.T) { 206 db := &mocks.FakeLinkDao{DeleteFn: okDelete} 207 cache := &mocks.FakeLinkDao{DeleteFn: okDelete} 208 209 r := shortener.NewLinkRepository(db, cache) 210 211 err := r.Delete(context.Background(), slug) 212 213 if err != nil { 214 t.Errorf("Unexpected error inserting link: %v", err) 215 } 216 217 if !cache.DeleteCalled { 218 t.Error("Expected cache to have been called") 219 } 220 }) 221 }