Skip to content

Instantly share code, notes, and snippets.

@illiafox
Created December 21, 2022 11:17
Show Gist options
  • Save illiafox/7ef964c41d00569e9c08818a4c49d14b to your computer and use it in GitHub Desktop.
Save illiafox/7ef964c41d00569e9c08818a4c49d14b to your computer and use it in GitHub Desktop.
package storages
import (
"context"
"math/rand"
"testing"
"github.com/golang/mock/gomock"
"github.com/google/uuid"
"github.com/illiafox/saga-shop/api/apptrace"
"github.com/illiafox/saga-shop/api/protos"
"github.com/illiafox/saga-shop/api/protos/mocks"
"github.com/illiafox/saga-shop/models"
"github.com/sirupsen/logrus"
"github.com/sirupsen/logrus/hooks/test"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
"go.opentelemetry.io/otel/sdk/trace/tracetest"
"go.opentelemetry.io/otel/trace"
)
func TestOrdersStorage(t *testing.T) {
suite.Run(t, new(GrpcClientSuite))
}
type GrpcClientSuite struct {
suite.Suite
// gRPC client
storageMocks *mocks.MockOrderServiceClient
storage GrpcOrdersStorage
// Tracing
traceExporter *tracetest.InMemoryExporter
tracer trace.Tracer
traceProvider *sdktrace.TracerProvider
// Logger
loggerHook *test.Hook
}
func (s *GrpcClientSuite) SetupSuite() {
ctrl := gomock.NewController(s.T())
s.storageMocks = mocks.NewMockOrderServiceClient(ctrl)
// Exporter
exp := tracetest.NewInMemoryExporter()
s.traceExporter = exp
// Provider
provider, err := apptrace.NewTraceProvider(exp, "TestService")
require.NoError(s.T(), err)
s.traceProvider = provider
// Tracer
tracer := provider.Tracer("TestTracer")
s.tracer = tracer
// Logger
logger, hook := test.NewNullLogger()
logger.Level = logrus.DebugLevel
s.loggerHook = hook
// Storage
s.storage = NewGrpcOrderStorage(s.storageMocks, tracer, logger)
}
func (s *GrpcClientSuite) SetupTest() {
// Reset spans storage before each test
s.traceExporter.Reset()
// Reset logger
s.loggerHook.Reset()
}
func (s *GrpcClientSuite) TearDownTest() {
// Flush all spans after the test
require.NoError(s.T(), s.traceProvider.ForceFlush(context.Background()))
// Get all recorded spans
spans := s.traceExporter.GetSpans()
require.Len(s.T(), spans, 2)
// Check whether the span is inherited from the parent span
// spans[1] - parent span
// spans[0] - inherited span
require.Equal(s.T(), spans[1].SpanContext, spans[0].Parent)
// Check debug logs
require.Equal(s.T(), 1, len(s.loggerHook.Entries))
require.Equal(s.T(), logrus.DebugLevel, s.loggerHook.LastEntry().Level)
}
func (s *GrpcClientSuite) Test_PlaceOrder() {
// Create expected variables
var (
product = models.Product{
ItemID: uuid.New(),
Price: rand.Uint64(),
Count: rand.Uint64(),
}
ExpectedUserID = uuid.New()
ExpectedOrderID = uuid.New()
)
// Mocks
s.storageMocks.EXPECT().
PlaceOrder(gomock.Any(), &protos.PlaceOrderRequest{
UserId: ExpectedUserID.String(),
Products: []*protos.Product{product.ToProto()},
}).
Return(&protos.PlaceOrderResponse{
OrderId: ExpectedOrderID.String(),
}, nil)
// Create new span
ctx, span := s.tracer.Start(context.Background(), "TestSpan")
defer span.End()
// Make call
orderID, err := s.storage.PlaceOrder(ctx, ExpectedUserID, []models.Product{product})
require.NoError(s.T(), err)
require.Equal(s.T(), ExpectedOrderID, orderID)
}
func (s *GrpcClientSuite) Test_GetOrderStatus() {
statuses := []models.OrderStatus{
models.StatusPendingAcceptance,
models.StatusAccepted,
models.StatusRejected,
}
for _, ExpectedStatus := range statuses {
// Convert status to proto
protoStatus, err := models.OrderStatusToProto(ExpectedStatus)
require.NoError(s.T(), err)
s.T().Run(protos.OrderStatus_name[int32(protoStatus)], func(t *testing.T) {
// Reset logger
s.SetupTest()
// Check tracer spans
defer s.TearDownTest()
ExpectedOrderID := uuid.New()
ExpectedReason := uuid.NewString()
s.storageMocks.EXPECT().
GetOrderStatus(gomock.Any(), &protos.GetOrderStatusRequest{
OrderId: ExpectedOrderID.String(),
}).
Return(&protos.GetOrderStatusResponse{
OrderStatus: protoStatus,
Reason: ExpectedReason,
}, nil)
// Create new span
ctx, span := s.tracer.Start(context.Background(), "TestSpan")
defer span.End()
// Make call
status, reason, err := s.storage.GetOrderStatus(ctx, ExpectedOrderID)
require.NoError(s.T(), err)
require.Equal(s.T(), ExpectedStatus, status)
require.Equal(s.T(), ExpectedReason, reason)
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment