go-sqlmock icon indicating copy to clipboard operation
go-sqlmock copied to clipboard

Unit test duplicate key SQLSTATE: 23505 error

Open Tak1za opened this issue 4 years ago • 1 comments
trafficstars

I'm trying to unit test a scenario where I get a duplicate key error but am not able to do the same.

service.go

func (s *service) addNewUser(newUser *models.User) error {
	newUser.ID = uuid.NewV4().String()
	if err := s.db.Client.Create(newUser).Error; err != nil {
		log.Println("error creating new user: ", err.Error())
		if pgError, ok := err.(*pgconn.PgError); ok {
			if pgError.Code == "23505" {
				errMessage := "user with the same email already exists"
				return errors.New(errMessage)
			}
			return errors.New(pgError.Message)
		}
		return err
	}

	return nil
}

service_test.go

func TestAddNewUser_Failure_DuplicateError(t *testing.T) {
	testDb, mock, _ := sqlmock.New()
	gormDB, _ := gorm.Open(postgres.New(postgres.Config{
		Conn: testDb,
	}))
	testNewUser := &models.User{
		Name:  "name",
		Email: "email",
	}

	mock.ExpectBegin()
	mock.ExpectExec(`INSERT INTO "users"`).WithArgs(
		AnyString{},
		AnyString{},
		AnyString{},
		AnyTime{},
		AnyTime{},
		nil).WillReturnError(&pgconn.PgError{
		Code: "23505",
	})
	mock.ExpectCommit()

	testService := &service{
		db: &db.Service{
			Client: gormDB,
		},
	}

	err := testService.addNewUser(testNewUser)
	assert.NotNil(t, err)
}

My unit test doesn't cover the lines:

if pgError.Code == "23505" {
    errMessage := "user with the same email already exists"
	return errors.New(errMessage)
}
return errors.New(pgError.Message)

Can someone help me understand why? Basically the conversion of err to pgconn.PGError does not work in the unit test, but it does work when I hit my service from the API layer.

Tak1za avatar Nov 15 '21 12:11 Tak1za