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  }