package assets import ( "errors" "testing" "src.dualinventive.com/go/assets-service/internal/domain" mtinfo "src.dualinventive.com/go/mtinfo-go" "github.com/stretchr/testify/require" ) var assetService *AssetService //nolint: gochecknoglobals var assetRepository *TestAssetRepository //nolint: gochecknoglobals func TestGetAssetByID_GivenUnknownID_ReturnsAssetNotFoundError(t *testing.T) { before(t) //given assetRepository.returnMe = []*domain.Asset{nil} assetRepository.returnErr = []error{nil} //when asset, err := assetService.GetAssetByID("", 123) //then require.Nil(t, asset) require.NotNil(t, err) require.EqualError(t, err, "asset not found") } func TestGetAssetByID_GivenKnownID_ReturnsAsset(t *testing.T) { before(t) //given assetRepository.returnMe = []*domain.Asset{ {ID: 123, UID: "someUID", SerialNr: "someSerialNr", TypeCode: "someTypeCode"}} assetRepository.returnErr = []error{nil} //when asset, err := assetService.GetAssetByID("", 123) //then require.NotNil(t, asset) require.Equal(t, asset.ID, uint(123)) require.Equal(t, asset.UID, "someUID") require.Equal(t, asset.SerialNr, "someSerialNr") require.Equal(t, asset.TypeCode, "someTypeCode") require.Nil(t, err) } func TestGetAssetsByID_WhenRepositoryError_ReturnsRepositoryError(t *testing.T) { before(t) //given assetRepository.returnMe = []*domain.Asset{nil} assetRepository.returnErr = []error{errors.New("some repository error")} //when asset, err := assetService.GetAssetByID("", 123) //then require.Nil(t, asset) require.NotNil(t, err) require.EqualError(t, err, "failed to fetch asset: some repository error") } func before(t *testing.T) { assetRepository = NewTestAssetRepository(t) assetService = &AssetService{ AssetRepository: assetRepository, Mtinfo: &mtinfo.Client{ Auth: &testAuthClient{}, }, } } func TestGetAssets_GivenCorrectParams_ReturnsAssets(t *testing.T) { before(t) //given assetRepository.returnMeMulti = [][]domain.Asset{{ {ID: 123, UID: "someUID", SerialNr: "someSerialNr", TypeCode: "someTypeCode"}, {ID: 321, UID: "otherUID", SerialNr: "otherSerialNr", TypeCode: "otherTypeCode"}, }} assetRepository.returnErr = []error{nil} //when assets, count, err := assetService.GetAssets("", 1, 1, "") //then require.NotNil(t, assets) require.Equal(t, count, uint64(2)) require.Equal(t, assets[0].UID, "someUID") require.Nil(t, err) } func TestGetAssets_GivenWrongParams_ReturnsInvalidArgument(t *testing.T) { testCases := []struct { paramPage uint64 paramPerPage uint64 }{ { paramPage: 0, // wrong paramPerPage: 1, }, { paramPage: 1, paramPerPage: 0, // wrong }, { paramPage: 1, paramPerPage: 201, // wrong }, } before(t) for _, tc := range testCases { //given assetRepository.returnMeMulti = [][]domain.Asset{nil} assetRepository.returnErr = []error{nil} //when assets, count, err := assetService.GetAssets("", tc.paramPage, tc.paramPerPage, "") //then require.Nil(t, assets) require.Equal(t, count, uint64(0)) require.IsType(t, new(ErrInvalidArgument), err) } } func TestGetAssets_WhenRepositoryError_ReturnsRepositoryError(t *testing.T) { before(t) //given assetRepository.returnMeMulti = [][]domain.Asset{nil} assetRepository.returnErr = []error{errors.New("some repository error")} //when assets, count, err := assetService.GetAssets("", 1, 1, "") //then require.Nil(t, assets) require.Equal(t, count, uint64(0)) require.IsType(t, new(ErrAssetRepositoryErr), err) } //NewTestAssetRepository returns a mockable asset repository. func NewTestAssetRepository(t *testing.T) *TestAssetRepository { return &TestAssetRepository{t: t, callCount: 0, returnMe: []*domain.Asset{nil}, returnErr: []error{nil}} } type TestAssetRepository struct { t *testing.T callCount int returnMe []*domain.Asset returnMeMulti [][]domain.Asset returnErr []error } func (r TestAssetRepository) GetAssetByID(assetID uint64) (*domain.Asset, error) { returnMe := r.returnMe[r.callCount] returnErr := r.returnErr[r.callCount] r.callCount++ return returnMe, returnErr } func (r TestAssetRepository) GetAssets( page uint64, perPage uint64, sort domain.SortCol) ( []domain.Asset, uint64, error) { returnMeMulti := r.returnMeMulti[r.callCount] returnErr := r.returnErr[r.callCount] r.callCount++ return returnMeMulti, uint64(len(returnMeMulti)), returnErr } //testAuthClient contains authentication related operations over GRPC type testAuthClient struct{} //VerifyToken verifies the given token to see if its valid. //When a public key is configured, token is locally verified using JWT. //When no public key is configured, token is remotely verified using GRPC. //Returns false when token signed portion is invalid, or token is expired. func (as *testAuthClient) VerifyToken(token string) (bool, error) { return true, nil } func (as *testAuthClient) VerifyTokenRemotely(token string) (bool, error) { return true, nil } func (as *testAuthClient) Login(username, companyCode, password string) (string, error) { return "", nil } func (as *testAuthClient) Logout(token string) error { return nil } func (as *testAuthClient) Me(token string) (*mtinfo.User, error) { return nil, nil } func (as *testAuthClient) RequestPasswordReset(username string) error { return nil } func (as *testAuthClient) RedeemPasswordReset(username, resetCode, password, passwordVerify string) error { return nil } func (as *testAuthClient) ListTokens(token string) (mtinfo.OpaqueTokens, error) { return nil, nil } func (as *testAuthClient) DeleteToken(token string, opaqueToken string) error { return nil } func (as *testAuthClient) UserAgent() string { return "" } func (as *testAuthClient) SetUserAgent(string) {}