package graphql_test import ( "context" "fmt" "strconv" "testing" "tercul/internal/adapters/graphql" "tercul/internal/adapters/graphql/model" "tercul/internal/app" "tercul/internal/app/analytics" "tercul/internal/app/like" "tercul/internal/domain" platform_auth "tercul/internal/platform/auth" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/suite" ) // LikeResolversUnitSuite is a unit test suite for the like resolvers. type LikeResolversUnitSuite struct { suite.Suite resolver *graphql.Resolver mockLikeRepo *mockLikeRepository mockWorkRepo *mockWorkRepository mockAnalyticsSvc *mockAnalyticsService } func (s *LikeResolversUnitSuite) SetupTest() { // 1. Create mock repositories s.mockLikeRepo = new(mockLikeRepository) s.mockWorkRepo = new(mockWorkRepository) s.mockAnalyticsSvc = new(mockAnalyticsService) // 2. Create real services with mock repositories likeService := like.NewService(s.mockLikeRepo) analyticsService := analytics.NewService(s.mockAnalyticsSvc, nil, nil, s.mockWorkRepo, nil) // 3. Create the resolver with the services s.resolver = &graphql.Resolver{ App: &app.Application{ Like: likeService, Analytics: analyticsService, }, } } func TestLikeResolversUnitSuite(t *testing.T) { suite.Run(t, new(LikeResolversUnitSuite)) } func (s *LikeResolversUnitSuite) TestCreateLike() { // 1. Setup workIDStr := "1" workIDUint64, _ := strconv.ParseUint(workIDStr, 10, 32) workIDUint := uint(workIDUint64) userID := uint(123) // Mock repository responses s.mockWorkRepo.On("Exists", mock.Anything, workIDUint).Return(true, nil) s.mockLikeRepo.On("Create", mock.Anything, mock.AnythingOfType("*domain.Like")).Run(func(args mock.Arguments) { arg := args.Get(1).(*domain.Like) arg.ID = 1 // Simulate database assigning an ID }).Return(nil) s.mockAnalyticsSvc.On("IncrementWorkCounter", mock.Anything, workIDUint, "likes", 1).Return(nil) // Create a context with an authenticated user ctx := platform_auth.ContextWithUserID(context.Background(), userID) // 2. Execution likeInput := model.LikeInput{ WorkID: &workIDStr, } createdLike, err := s.resolver.Mutation().CreateLike(ctx, likeInput) // 3. Assertions s.Require().NoError(err) s.Require().NotNil(createdLike) s.Equal("1", createdLike.ID) s.Equal(fmt.Sprintf("%d", userID), createdLike.User.ID) // Verify that the repository's Create method was called s.mockLikeRepo.AssertCalled(s.T(), "Create", mock.Anything, mock.MatchedBy(func(l *domain.Like) bool { return *l.WorkID == workIDUint && l.UserID == userID })) // Verify that analytics was called s.mockAnalyticsSvc.AssertCalled(s.T(), "IncrementWorkCounter", mock.Anything, workIDUint, "likes", 1) } func (s *LikeResolversUnitSuite) TestDeleteLike() { // 1. Setup likeIDStr := "1" likeIDUint, _ := strconv.ParseUint(likeIDStr, 10, 32) userID := uint(123) // Mock the repository response for the initial 'find' s.mockLikeRepo.On("GetByID", mock.Anything, uint(likeIDUint)).Return(&domain.Like{ BaseModel: domain.BaseModel{ID: uint(likeIDUint)}, UserID: userID, }, nil) // Mock the repository response for the 'delete' s.mockLikeRepo.On("Delete", mock.Anything, uint(likeIDUint)).Return(nil) // Create a context with an authenticated user ctx := platform_auth.ContextWithUserID(context.Background(), userID) // 2. Execution deleted, err := s.resolver.Mutation().DeleteLike(ctx, likeIDStr) // 3. Assertions s.Require().NoError(err) s.True(deleted) // Verify that the repository's Delete method was called s.mockLikeRepo.AssertCalled(s.T(), "Delete", mock.Anything, uint(likeIDUint)) }