【Go单元测试】停止使用gomock.any()
应该避免在单元测试中使用gomock.any(),使用gomock.any()让你的单元测试更容易通过的同时也会降低单元测试的可信度。
举个例子
业务描述
一个简单的新增学生信息功能,记录一个学生的时候,除了基本信息外,还需要从评价系统获取该学生的评价信息存入数据库。
domain层
type Student struct {
ID uint `json:"id"`
UUID string `json:"uuid"`
Age int `json:"age"`
Name string `json:"name"`
Assessment string `json:"assessment"` // 评价信息
}
usecase层
type StudentUsecase struct {
repo domain.IStudentUsecase
assService infra.AssessmentService
}
func (s *StudentUsecase) Create(student domain.Student) error {
// 从评价服务获取该学生的评价信息
assessment, err := s.assService.GetAssessment(student.UUID)
if err != nil {
return err
}
student.Assessment = assessment
return s.repo.Create(student)
}
usecase测试用例
func TestStudentUsecaseCreate(t *testing.T) {
ctl := gomock.NewController(t)
defer ctl.Finish()
repo:=mocks.NewMockIStudentRepo(ctl)
assService :=mocks2.NewMockAssessmentService(ctl)
student:=domain.Student{
ID: 100,
UUID: "uuid1",
Age: 24,
Name: "seven",
}
assService.EXPECT().GetAssessment(gomock.Any()).Return("a good student",nil)
repo.EXPECT().Create(gomock.Any()).Return(nil)
usecase := &StudentUsecase{
repo: repo,
assService: assService,
}
if err:=usecase.Create(student);err!=nil{
t.Fail()
}
}
这样的测试用例能正确执行,也能增加项目的整体覆盖率,但是这是一个假的测试用例,这种写法忽略了一个重要的事情,usecase.Create的入参校验。正确的写法应该如下:
func TestStudentUsecaseCreate2(t *testing.T) {
ctl := gomock.NewController(t)
defer ctl.Finish()
repo:=mocks.NewMockIStudentRepo(ctl)
assService :=mocks2.NewMockAssessmentService(ctl)
student:=domain.Student{
ID: 100,
UUID: "uuid1",
Age: 24,
Name: "seven",
}
assService.EXPECT().GetAssessment("uuid1").Return("a good student",nil)
repo.EXPECT().Create(gomock.Eq(domain.Student{
ID: 100,
UUID: "uuid1",
Age: 24,
Name: "seven",
Assessment: "a good student",
})).Return(nil)
usecase := &StudentUsecase{
repo: repo,
assService: assService,
}
if err:=usecase.Create(student);err!=nil{
t.Fail()
}
}
这个测试用例包含了两次参数校验,一个是学生的UUID,另一个是Assessment信息。这样的单元测试才是有意义的。
总结
要对自己写的单元测试负责,单元测试和业务代码一样重要。让我们从少用甚至是不用gomock.any()开始。
- 原文作者:seven.yu
- 原文链接:https://sevenyu.top/2021-04-02-stop-use-gomock.any.html
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。