如何为单元测试模拟数据库

huangapple go评论78阅读模式
英文:

How to mock DB for unit tests

问题

我有一个类似这样的UserRepo:

type users struct {
	*gorm.DB
}

func NewMySqlUsersRepository(db *gorm.DB) repository.IUsers {
	return &users{
		DB: db,
	}
}

对应的方法实现如下:

func (r *users) Save(user *domain.User) (*domain.User, *errors.RestErr) {
	err := r.DB.Model(&domain.User{}).Create(&user).Error

	if err != nil {
		logger.Error("创建用户时发生错误", err)
		return nil, errors.NewInternalServerError(errors.ErrSomethingWentWrong)
	}

	return user, nil
}

对于数据库的模拟,我正在使用sqlmock。但是如何为单元测试模拟这个方法呢?在Gorm中如何为其他数据库查询进行模拟?

英文:

I have UserRepo like this:

type users struct {
   *gorm.DB
}

func NewMySqlUsersRepository(db *gorm.DB) repository.IUsers {
	return &users{
    	DB: db,
	}
}

Corresponding methods implementation

func (r *users) Save(user *domain.User) (*domain.User, *errors.RestErr) {
  err := r.DB.Model(&domain.User{}).Create(&user).Error

  if err != nil {
	logger.Error("error occurred when create user", err)
 	return nil, errors.NewInternalServerError(errors.ErrSomethingWentWrong)
  }

  return user, nil
}

For database mock, I am using sqlmock. But how do I mock this method for unit tests? And in Gorm how to mock for other databases queries?

答案1

得分: 1

在Go语言中进行模拟测试主要是基于Go接口。你需要为存储库创建一个接口,并实现接口的方法。

type IUserRepository interface {
    save(user *UserModel) (*userModel, Err)
}

现在,你只需要创建一个模拟结构体和用户结构体,这两个结构体都要实现IUserRepository接口。你可能还想使用流行的模拟/测试框架,比如go-mocktestify来创建模拟对象。

接下来,你需要实现一个工厂方法,根据条件返回相应的模拟结构体。你可以通过上下文、环境变量或其他方式注入条件变量。

func NewMySqlUsersRepositoryFactory(ctx context.Context, env string, db *gorm.DB) repository.IUsers {
    if env == "test" {
        // 这是一个模拟结构体...
        return mock.MockUsers{}
    }
    // 这是一个实际的结构体...
    return &users{
        DB: db,
    }
}

希望对你有帮助!

英文:

Mocking in Go Is all about Go Interfaces. You will have to create an interface for the repository and implement the Interface methods.

type interface IUserRepository{
     save(user *UserModel) (*userModel, Err)
}

Now all you need to do is to create a mock struct along with the user struct. Both of these structs will implement IUserRepository. You might also want to use Popular mocking/testing frameworks like go-mock or testify for creating mocks.

Now, you will have to implement a factory method such that it will return mockStruct depending on the condition. You can inject the condition variable with context, env variable, or any other way.

func NewMySqlUsersRepositoryFactory(ctx context.Context, env string, db *gorm.DB) repository.IUsers {
	if env == "test" {
        // This is a mocked struct ...
		return mock.MockUsers{}
	}
     // This is a actual struct... 
	return &users{
        DB: db,
    }
}

huangapple
  • 本文由 发表于 2021年7月19日 19:47:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/68439982.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定