Skip to content

Commit

Permalink
100% coverage on uc articles
Browse files Browse the repository at this point in the history
  • Loading branch information
Matthieu Jacquot committed Aug 10, 2018
1 parent 833b012 commit d299704
Show file tree
Hide file tree
Showing 11 changed files with 451 additions and 197 deletions.
111 changes: 0 additions & 111 deletions uc/article.go

This file was deleted.

10 changes: 10 additions & 0 deletions uc/articleDelete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package uc

func (i interactor) ArticleDelete(username string, slug string) error {
_, err := i.getArticleAndCheckUser(username, slug)
if err != nil {
return err
}

return i.articleRW.Delete(slug)
}
72 changes: 72 additions & 0 deletions uc/articleDelete_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package uc_test

import (
"testing"

"errors"

"github.com/err0r500/go-realworld-clean/domain"
"github.com/err0r500/go-realworld-clean/implem/uc.mock"
"github.com/err0r500/go-realworld-clean/testData"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
)

func TestInteractor_ArticleDelete_happycase(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
jane := testData.User("jane")
article := testData.Article("janeArticle")

i := mock.NewMockedInteractor(mockCtrl)
i.ArticleRW.EXPECT().GetBySlug(article.Slug).Return(&article, nil).Times(1)
i.ArticleRW.EXPECT().Delete(article.Slug)

assert.NoError(t, i.GetUCHandler().ArticleDelete(jane.Name, article.Slug))
}

func TestInteractor_ArticleDelete_fails(t *testing.T) {
mutations := map[string]mock.Tester{
"shouldPass": {
Calls: func(i *mock.Interactor) { // change nothing
},
ShouldPass: true},
"error return on aRW.GetBySlug": {
Calls: func(i *mock.Interactor) {
i.ArticleRW.EXPECT().GetBySlug(gomock.Any()).Return(nil, errors.New(""))
}},
"wrong author return on aRW.GetBySlug": {
Calls: func(i *mock.Interactor) {
i.ArticleRW.EXPECT().GetBySlug(gomock.Any()).Return(&domain.Article{Author: domain.User{Name: "heyhey"}}, nil)
}},
"error return on delete": {
Calls: func(i *mock.Interactor) {
i.ArticleRW.EXPECT().Delete(gomock.Any()).Return(errors.New(""))
}},
}
jane := testData.User("jane")
article := testData.Article("janeArticle")

// same as the happy case but with any parameter and called any number of times (including 0)
validCalls := func(i *mock.Interactor) {
i.ArticleRW.EXPECT().GetBySlug(gomock.Any()).Return(&article, nil).AnyTimes()
i.ArticleRW.EXPECT().Delete(gomock.Any()).AnyTimes()
}

for testName, mutation := range mutations {
t.Run(testName, func(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
i := mock.NewMockedInteractor(mockCtrl)
mutation.Calls(&i) // put the tested call first (important)
validCalls(&i) // then fill the gaps with valid calls

err := i.GetUCHandler().ArticleDelete(jane.Name, article.Slug)
if mutation.ShouldPass {
assert.NoError(t, err)
return
}
assert.Error(t, err)
})
}
}
21 changes: 21 additions & 0 deletions uc/articleGet.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package uc

import "github.com/err0r500/go-realworld-clean/domain"

func (i interactor) ArticleGet(username, slug string) (*domain.User, *domain.Article, error) {
var user *domain.User
if username != "" {
var errGet error
user, errGet = i.userRW.GetByName(username)
if errGet != nil {
return nil, nil, errGet
}
}

article, err := i.articleRW.GetBySlug(slug)
if err != nil {
return nil, nil, err
}

return user, article, nil
}
69 changes: 69 additions & 0 deletions uc/articleGet_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package uc_test

import (
"testing"

"errors"

"github.com/err0r500/go-realworld-clean/implem/uc.mock"
"github.com/err0r500/go-realworld-clean/testData"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
)

func TestInteractor_ArticleGet_happycase(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
testUser := testData.User("rick")
article := testData.Article("janeArticle")

i := mock.NewMockedInteractor(mockCtrl)
i.ArticleRW.EXPECT().GetBySlug(article.Slug).Return(&article, nil).Times(1)
i.UserRW.EXPECT().GetByName(testUser.Name).Return(&testUser, nil).Times(1)

_, _, err := i.GetUCHandler().ArticleGet(testUser.Name, article.Slug)
assert.NoError(t, err)
}

func TestInteractor_ArticleGet_fails(t *testing.T) {
mutations := map[string]mock.Tester{
"shouldPass": {
Calls: func(i *mock.Interactor) { // change nothing
},
ShouldPass: true},
"error return on uRW.GetByName": {
Calls: func(i *mock.Interactor) {
i.UserRW.EXPECT().GetByName(gomock.Any()).Return(nil, errors.New(""))
}},
"error return on aRW.GetBySlug": {
Calls: func(i *mock.Interactor) {
i.ArticleRW.EXPECT().GetBySlug(gomock.Any()).Return(nil, errors.New(""))
}},
}

testUser := testData.User("rick")
article := testData.Article("janeArticle")

// same as the happy case but with any parameter and called any number of times (including 0)
validCalls := func(i *mock.Interactor) {
i.ArticleRW.EXPECT().GetBySlug(gomock.Any()).Return(&article, nil).AnyTimes()
i.UserRW.EXPECT().GetByName(gomock.Any()).Return(&testUser, nil).AnyTimes()
}

for testName, mutation := range mutations {
t.Run(testName, func(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
i := mock.NewMockedInteractor(mockCtrl)
mutation.Calls(&i) // put the tested call first (important)
validCalls(&i) // then fill the gaps with valid calls

_, _, err := i.GetUCHandler().ArticleGet(testUser.Name, article.Slug)
if mutation.ShouldPass {
assert.NoError(t, err)
return
}
assert.Error(t, err)
})
}
}
35 changes: 35 additions & 0 deletions uc/articlePost.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package uc

import (
"github.com/err0r500/go-realworld-clean/domain"
)

func (i interactor) ArticlePost(username string, article domain.Article) (*domain.User, *domain.Article, error) {
user, err := i.userRW.GetByName(username)
if err != nil {
return nil, nil, err
}

slug := i.slugger.NewSlug(article.Title)
if _, err := i.articleRW.GetBySlug(slug); err == nil {
return nil, nil, ErrAlreadyInUse
}

article.Slug = slug
article.Author = *user

if err := i.articleValidator.BeforeCreationCheck(&article); err != nil {
return nil, nil, err
}

completeArticle, err := i.articleRW.Create(article)
if err != nil {
return nil, nil, err
}

if err := i.tagsRW.Add(article.TagList); err != nil {
return nil, nil, err
}

return user, completeArticle, nil
}
Loading

0 comments on commit d299704

Please sign in to comment.