mirror of
				https://github.com/3ybactuk/marketplace-go-service-project.git
				synced 2025-10-30 22:13:44 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			231 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			231 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| //go:build integration
 | ||
| // +build integration
 | ||
| 
 | ||
| package integration
 | ||
| 
 | ||
| import (
 | ||
| 	"context"
 | ||
| 	"database/sql"
 | ||
| 	"fmt"
 | ||
| 	"net"
 | ||
| 	"testing"
 | ||
| 	"time"
 | ||
| 
 | ||
| 	"github.com/jackc/pgx/v5/pgxpool"
 | ||
| 	_ "github.com/jackc/pgx/v5/stdlib"
 | ||
| 	"github.com/ozontech/allure-go/pkg/framework/provider"
 | ||
| 	"github.com/ozontech/allure-go/pkg/framework/suite"
 | ||
| 	"github.com/pressly/goose/v3"
 | ||
| 	"github.com/testcontainers/testcontainers-go"
 | ||
| 	"github.com/testcontainers/testcontainers-go/wait"
 | ||
| 	"google.golang.org/grpc"
 | ||
| 	"google.golang.org/grpc/credentials/insecure"
 | ||
| 
 | ||
| 	repo "route256/comments/infra/repository/sqlc"
 | ||
| 	"route256/comments/internal/app/server"
 | ||
| 	"route256/comments/internal/domain/service"
 | ||
| 	pb "route256/pkg/api/comments/v1"
 | ||
| )
 | ||
| 
 | ||
| const (
 | ||
| 	migrationsDir = "../../db/migrations"
 | ||
| )
 | ||
| 
 | ||
| func startPostgres(ctx context.Context, migrationsDir string) (*pgxpool.Pool, func(), error) {
 | ||
| 	req := testcontainers.ContainerRequest{
 | ||
| 		Image: "gitlab-registry.ozon.dev/go/classroom-18/students/base/postgres:16",
 | ||
| 		Env: map[string]string{
 | ||
| 			"POSTGRESQL_USERNAME": "user",
 | ||
| 			"POSTGRESQL_PASSWORD": "postgres",
 | ||
| 			"POSTGRESQL_DATABASE": "comments_test",
 | ||
| 		},
 | ||
| 		ExposedPorts: []string{"5432/tcp"},
 | ||
| 		WaitingFor:   wait.ForListeningPort("5432/tcp").WithStartupTimeout(30 * time.Second),
 | ||
| 	}
 | ||
| 	container, err := testcontainers.GenericContainer(ctx,
 | ||
| 		testcontainers.GenericContainerRequest{ContainerRequest: req, Started: true})
 | ||
| 	if err != nil {
 | ||
| 		return nil, nil, err
 | ||
| 	}
 | ||
| 
 | ||
| 	endpoint, err := container.PortEndpoint(ctx, "5432", "")
 | ||
| 	if err != nil {
 | ||
| 		container.Terminate(ctx)
 | ||
| 		return nil, nil, err
 | ||
| 	}
 | ||
| 
 | ||
| 	dsn := fmt.Sprintf("postgresql://user:postgres@%s/comments_test?sslmode=disable", endpoint)
 | ||
| 
 | ||
| 	var pool *pgxpool.Pool
 | ||
| 	for i := 0; i < 30; i++ {
 | ||
| 		pool, err = pgxpool.New(ctx, dsn)
 | ||
| 		if err == nil && pool.Ping(ctx) == nil {
 | ||
| 			break
 | ||
| 		}
 | ||
| 		time.Sleep(1 * time.Second)
 | ||
| 	}
 | ||
| 	if err != nil {
 | ||
| 		container.Terminate(ctx)
 | ||
| 		return nil, nil, err
 | ||
| 	}
 | ||
| 
 | ||
| 	std, err := sql.Open("pgx", dsn)
 | ||
| 	if err != nil {
 | ||
| 		container.Terminate(ctx)
 | ||
| 		return nil, nil, err
 | ||
| 	}
 | ||
| 
 | ||
| 	if err := goose.Up(std, migrationsDir); err != nil {
 | ||
| 		container.Terminate(ctx)
 | ||
| 		return nil, nil, err
 | ||
| 	}
 | ||
| 	std.Close()
 | ||
| 
 | ||
| 	cleanup := func() {
 | ||
| 		pool.Close()
 | ||
| 		_ = container.Terminate(context.Background())
 | ||
| 	}
 | ||
| 	return pool, cleanup, nil
 | ||
| }
 | ||
| 
 | ||
| type Suite struct {
 | ||
| 	suite.Suite
 | ||
| 
 | ||
| 	grpcSrv  *grpc.Server
 | ||
| 	grpcConn *grpc.ClientConn
 | ||
| 
 | ||
| 	client pb.CommentsClient
 | ||
| 
 | ||
| 	cleanup func()
 | ||
| }
 | ||
| 
 | ||
| func TestLomsIntegrationSuite(t *testing.T) {
 | ||
| 	suite.RunSuite(t, new(Suite))
 | ||
| }
 | ||
| 
 | ||
| func (s *Suite) BeforeAll(t provider.T) {
 | ||
| 	ctx := context.Background()
 | ||
| 	t.WithNewStep("init cart-service", func(sCtx provider.StepCtx) {
 | ||
| 		pool, cleanup, err := startPostgres(ctx, migrationsDir)
 | ||
| 		sCtx.Require().NoError(err, "failed postgres setup")
 | ||
| 
 | ||
| 		s.cleanup = cleanup
 | ||
| 
 | ||
| 		repo := repo.NewCommentsRepository(pool, pool)
 | ||
| 
 | ||
| 		svc := service.NewCommentsService(repo, 1)
 | ||
| 
 | ||
| 		commentsServer := server.NewServer(svc)
 | ||
| 
 | ||
| 		lis, err := net.Listen("tcp", "127.0.0.1:0")
 | ||
| 		sCtx.Require().NoError(err)
 | ||
| 
 | ||
| 		s.grpcSrv = grpc.NewServer()
 | ||
| 		pb.RegisterCommentsServer(s.grpcSrv, commentsServer)
 | ||
| 
 | ||
| 		go func() { _ = s.grpcSrv.Serve(lis) }()
 | ||
| 
 | ||
| 		time.Sleep(50 * time.Millisecond)
 | ||
| 
 | ||
| 		conn, err := grpc.NewClient(lis.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock())
 | ||
| 		sCtx.Require().NoError(err)
 | ||
| 
 | ||
| 		s.grpcConn = conn
 | ||
| 		s.client = pb.NewCommentsClient(conn)
 | ||
| 	})
 | ||
| }
 | ||
| 
 | ||
| func (s *Suite) AfterAll(t provider.T) {
 | ||
| 	s.grpcSrv.Stop()
 | ||
| 	_ = s.grpcConn.Close()
 | ||
| 	s.cleanup()
 | ||
| }
 | ||
| 
 | ||
| func (s *Suite) TestCommentListByOneUser_Success(t provider.T) {
 | ||
| 	t.Title("Успешное получение списка комментариев, которые оставил один юзер по SKU")
 | ||
| 
 | ||
| 	ctx := context.Background()
 | ||
| 
 | ||
| 	const (
 | ||
| 		userID       = int64(40)
 | ||
| 		sku          = int64(40)
 | ||
| 		commentText1 = "тестовый комментарий 1"
 | ||
| 		commentText2 = "тестовый комментарий 2"
 | ||
| 	)
 | ||
| 
 | ||
| 	var (
 | ||
| 		commentIDs []int64
 | ||
| 		commentID  int64
 | ||
| 	)
 | ||
| 
 | ||
| 	t.WithNewParameters("userID", userID, "sku", sku)
 | ||
| 
 | ||
| 	t.WithNewStep("Создание комментария 1", func(sCtx provider.StepCtx) {
 | ||
| 		req := &pb.CreateCommentRequest{
 | ||
| 			UserId:  userID,
 | ||
| 			Sku:     sku,
 | ||
| 			Comment: commentText1,
 | ||
| 		}
 | ||
| 		resp, err := s.client.CommentAdd(ctx, req)
 | ||
| 		sCtx.Require().NoError(err)
 | ||
| 		commentID = resp.Id
 | ||
| 
 | ||
| 		commentIDs = append(commentIDs, commentID)
 | ||
| 	})
 | ||
| 
 | ||
| 	t.WithNewParameters("commentID1", commentID)
 | ||
| 
 | ||
| 	t.WithNewStep("Получение первого созданного комментария", func(sCtx provider.StepCtx) {
 | ||
| 		req := &pb.ListByUserRequest{
 | ||
| 			UserId: userID,
 | ||
| 		}
 | ||
| 		resp, err := s.client.CommentListByUser(ctx, req)
 | ||
| 		sCtx.Require().NoError(err)
 | ||
| 
 | ||
| 		sCtx.Require().Len(resp.Comments, 1)
 | ||
| 		sCtx.Require().NotNil(resp.Comments[0])
 | ||
| 
 | ||
| 		resultComment := resp.Comments[0]
 | ||
| 
 | ||
| 		sCtx.Require().Equal(commentID, resultComment.Id)
 | ||
| 		sCtx.Require().Equal(sku, resultComment.Sku)
 | ||
| 		sCtx.Require().Equal(commentText1, resultComment.Text)
 | ||
| 	})
 | ||
| 
 | ||
| 	t.WithNewStep("Создание комментария 2", func(sCtx provider.StepCtx) {
 | ||
| 		req := &pb.CreateCommentRequest{
 | ||
| 			UserId:  userID,
 | ||
| 			Sku:     sku,
 | ||
| 			Comment: commentText2,
 | ||
| 		}
 | ||
| 		resp, err := s.client.CommentAdd(ctx, req)
 | ||
| 		sCtx.Require().NoError(err)
 | ||
| 
 | ||
| 		commentID = resp.Id
 | ||
| 		commentIDs = append(commentIDs, commentID)
 | ||
| 	})
 | ||
| 
 | ||
| 	t.WithNewParameters("commentID2", commentID)
 | ||
| 
 | ||
| 	t.WithNewStep("Получение созданных комментариев в обратном хронологическом порядке", func(sCtx provider.StepCtx) {
 | ||
| 		req := &pb.ListByUserRequest{
 | ||
| 			UserId: userID,
 | ||
| 		}
 | ||
| 		resp, err := s.client.CommentListByUser(ctx, req)
 | ||
| 		sCtx.Require().NoError(err)
 | ||
| 
 | ||
| 		sCtx.Require().Len(resp.Comments, 2)
 | ||
| 		sCtx.Require().NotNil(resp.Comments[0])
 | ||
| 		sCtx.Require().NotNil(resp.Comments[1])
 | ||
| 
 | ||
| 		// commentIDs содержит в себе id комментариев в прямом хронологическом порядке
 | ||
| 		sCtx.Require().Equal(commentIDs[1], resp.Comments[0].Id)
 | ||
| 		sCtx.Require().Equal(sku, resp.Comments[0].Sku)
 | ||
| 		sCtx.Require().Equal(commentText2, resp.Comments[0].Text)
 | ||
| 
 | ||
| 		sCtx.Require().Equal(commentIDs[0], resp.Comments[1].Id)
 | ||
| 		sCtx.Require().Equal(sku, resp.Comments[1].Sku)
 | ||
| 		sCtx.Require().Equal(commentText1, resp.Comments[1].Text)
 | ||
| 	})
 | ||
| }
 | 
