DATA-DOG / go-sqlmock

Sql mock driver for golang to test database interactions
Other
6.02k stars 406 forks source link

Unit test duplicate key SQLSTATE: 23505 error #278

Open Tak1za opened 2 years ago

Tak1za commented 2 years ago

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.

diegommm commented 2 months ago

Hi @Tak1za! Have you tried using errors.As instead of directly type-asserting? Errors are often wrapped.