[英]Check dynamic value for field in struct in go using testify
I have a user service
that validates the user data and formats it and then calls Firebase service which creates a firebase user and return firebase id and then it pass that user data to repository
layer.我有一个
user service
,它验证用户数据并对其进行格式化,然后调用 Firebase 服务,该服务创建一个 firebase 用户并返回repository
id,然后将其传递给数据层。 My user struct has an ID
field is populated by uuid
in user service
before passing to repository
layer.我的用户结构有一个
ID
字段,在传递到repository
层之前由user service
中的uuid
填充。 I am mocking the firebase service and repository layer using strecher/testify
.我是 mocking firebase 服务和存储库层使用
strecher/testify
。 But the test is failing since the ID
is populated by service layer and I cannot pass the ID
to the user data used by mock function.但测试失败,因为
ID
由服务层填充,我无法将ID
传递给模拟 function 使用的用户数据。
user := model.User{
ID: "",
FirebaseID: "",
FirstName: "Test",
LastName: "User",
FullName: "Test User",
Email: "testuser@email.com"
Password: "password",
}
Service layer code服务层代码
func (u userService) CreateUser(user model.User) error {
err := validateFields(user)
if err != nil {
return fmt.Errorf("userService CreateUser: %w", err)
}
user.FullName = user.FirstName + " " + user.LastName
user.FirebaseID, err = u.authClient.CreateUser(user)
if err != nil {
return fmt.Errorf("userService CreateUser: %w", err)
}
user.ID = uuid.NewString()
err = u.userRepo.CreateUser(user)
if err != nil {
return fmt.Errorf("userService CreateUser: %w", err)
}
return nil
} }
Test code测试代码
func TestCreateUser(t *testing.T) {
mockFirebaseAuthClient := new(MockFirebaseAuthClient)
mockPostgresRepo := new(MockPostgresRepo)
userService := NewUserService(mockPostgresRepo, mockFirebaseAuthClient)
t.Run("Valid data", func(t *testing.T) {
user := model.User{
ID: "",
FirebaseID: "firebaseuniqueid",
FirstName: "Test",
LastName: "User",
FullName: "Test User",
Email: "testuser@email.com",
Password: "password",
}
mockFirebaseAuthClient.On("CreateUser", user).Return("firebaseuniqueid", nil)
mockPostgresRepo.On("CreateUser", user).Return(nil)
err := userService.CreateUser(user)
if err != nil {
t.Fatalf("Expectd: nil, got: %v", err)
}
})
Error while testing测试时出错
mock: Unexpected Method Call
-----------------------------
CreateUser(model.User)
0: model.User{ID:"f87fd2f3-5801-4359-a565-a4eb13a6de37", FirebaseID:"firebaseuniqueid", FirstName:"Test", LastName:"User", FullName:"Test User", Email:"testuser@email.com", Password:"password"}
The closest call I have is:
CreateUser(model.User)
0: model.User{ID:"", FirebaseID:"firebaseuniqueid", FirstName:"Test", LastName:"User", FullName:"Test User", Email:"testuser@email.com", Password:"password"}
Difference found in argument 0:
--- Expected
+++ Actual
@@ -1,3 +1,3 @@
(model.User) {
- ID: (string) "",
+ ID: (string) (len=36) "f87fd2f3-5801-4359-a565-a4eb13a6de37",
FirebaseID: (string) (len=16) "firebaseuniqueid",
Diff: 0: FAIL: (model.User={f87fd2f3-5801-4359-a565-a4eb13a6de37 firebaseuniqueid Test User Test User testuser@email.com password}) != (model.User={ firebaseuniqueid Test User Test User testuser@email.com password}) [recovered]
Is there any way I could check the dynamically created uuid or ignore the values in the struct in the test?有什么方法可以检查动态创建的 uuid 或忽略测试中结构中的值?
if you don't want to consider mockFirebaseAuthClient.On("CreateUser", user).Return("firebaseuniqueid", nil)
and mockPostgresRepo.On("CreateUser", user).Return(nil)
and just want to mock that calls, then you can use mock.Anything
as the argument in both the calls instead of user
like this mockFirebaseAuthClient.On("CreateUser", mock.Anything).Return("firebaseuniqueid", nil)
.如果您不想考虑
mockFirebaseAuthClient.On("CreateUser", user).Return("firebaseuniqueid", nil)
和mockPostgresRepo.On("CreateUser", user).Return(nil)
并且只想模拟调用,那么您可以在两个调用中使用mock.Anything
作为参数,而不是像这样的user
mockFirebaseAuthClient.On("CreateUser", mock.Anything).Return("firebaseuniqueid", nil)
。 So the arguments will not be considerd and the mock calls will return required value.所以 arguments 将不被考虑,模拟调用将返回所需的值。
Regarding your question of关于你的问题
Since uuid is not injected into the service layer, how can it be mocked?
既然uuid没有注入到服务层,那怎么mock呢? It is an imported package.
是进口的package。
Like this, first, define an interface with the same method we want to mock像这样,首先,定义一个与我们要模拟的方法相同的接口
type uuidGen interface {
String() string
}
Then, define a mock type in which we're going to define our method然后,定义一个模拟类型,我们将在其中定义我们的方法
type mockGen struct{}
Then, define the method on the type然后,在类型上定义方法
func (u *mockGen) String() string {
return "test"
}
Update CreateUser
function to receive a uuidGen
parameter that shares the method String()
with uuid
's package.更新
CreateUser
function 以接收与uuid
的 package 共享方法String()
的uuidGen
参数。
func (u userService) CreateUser(uuid uuidGen, user User) error {
err := validateFields(user)
if err != nil {
return fmt.Errorf("userService CreateUser: %w", err)
}
user.FullName = user.FirstName + " " + user.LastName
user.FirebaseID, err = u.authClient.CreateUser(user)
if err != nil {
return fmt.Errorf("authClient CreateUser: %w", err)
}
user.ID = uuid.String()
err = u.userRepo.CreateUser(user)
if err != nil {
return fmt.Errorf("userService CreateUser: %w", err)
}
return nil
}
Now we can write the test like this, see how the 2 methods accept different types that implement the interface uuidGen
and can call a method String()
现在我们可以这样写测试,看看这2个方法如何接受实现接口
uuidGen
的不同类型并且可以调用方法String()
func TestCreateUser(t *testing.T) {
mockFirebaseAuthClient := new(MockFirebaseAuthClient)
mockPostgresRepo := new(MockPostgresRepo)
userService := NewUserService("test", "test")
t.Run("Valid data", func(t *testing.T) {
user := User{
ID: "",
FirebaseID: "firebaseuniqueid",
FirstName: "Test",
LastName: "User",
FullName: "Test User",
Email: "testuser@email.com",
Password: "password",
}
mockFirebaseAuthClient.On("CreateUser", user).Return("firebaseuniqueid", nil)
mockPostgresRepo.On("CreateUser", user).Return(nil)
gen := new(mockGen)
err := userService.CreateUser(gen, user)
if err != nil {
t.Fatalf("Expectd: nil, got: %v", err)
}
realUUID := uuid.New()
err = userService.CreateUser(realUUID, user)
if err != nil {
t.Fatalf("Expectd: nil, got: %v", err)
}
t.Log("Mock UUID:", gen.String()) // prints test
t.Log("Real UUID UUID:", realUUID.String()) // prints a UUID
})
}
Run it with go test -v
to see the output of t.Log(...)
使用
go test -v
运行它以查看t.Log(...)
的 output
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.