Golang 模拟上下文恐慌
Golang mock context panic
所以我在 golang 中使用 mockery and testify
进行单元测试
测试代码如下:
const bufSize = 1024 * 1024
var lis *bufconn.Listener
var mockAccountService = &mocks.AccountService{}
func init() {
lis = bufconn.Listen(bufSize)
s := grpc.NewServer()
RegisterAccountManagementHandlerServer(s, &server{mockAccountService})
go func() {
if err := s.Serve(lis); err != nil {
log.Fatalf("Server exited with error: %v", err)
}
}()
}
func bufDialer(context.Context, string) (net.Conn, error) {
return lis.Dial()
}
func TestSayHello(t *testing.T) {
var a uint64 = 1
ctx := context.Background()
conn, err := grpc.DialContext(ctx, "bufnet", grpc.WithContextDialer(bufDialer), grpc.WithInsecure())
if err != nil {
t.Fatalf("Failed to dial bufnet: %v", err)
}
defer conn.Close()
client := NewAccountManagementHandlerClient(conn)
mockAccountService.On("GetSavingAccount", context.Background(), a, a, "Hello", 1).Return(&models.SavingAccount{
CustomerID: 1,
ID: 1,
CardNo: "Hello",
SavingProductID: 1,
Balance: 0,
Status: 1,
})
resp, err := client.GetSavingAccount(ctx, &GetSavingAccountDataRequest{
Id: 1,
CustomerId: 1,
CardNo: "Hello",
SavingProductId: 1,
})
if err != nil {
t.Fatalf("SayHello failed: %v", err)
}
fmt.Printf("Response: %+v", resp)
// Test for output here.
但是我得到这样的错误:
panic:
mock: Unexpected Method Call
-----------------------------
GetSavingAccount(*context.valueCtx,uint64,uint64,string,int64)
0: &context.valueCtx{Context:(*context.valueCtx)(0xc000115260), key:grpc.streamKey{}, val:(*transport.Stream)(0xc0004a2200)}
1: 0x1
2: 0x1
3: "Hello"
4: 1
The closest call I have is:
GetSavingAccount(mock.AnythingOfTypeArgument,uint64,uint64,string,int)
0: "&context.ValueCtx"
1: 0x1
2: 0x1
3: "Hello"
4: 1
我应该将什么值传递给 mock context.Background()
?
我试过mock.AnythingOfType("&context.emptyCtx")
,mock.Anything
,没用
谢谢
编辑:
我试过了
mockAccountService.On("GetSavingAccount", context.Background(), a, a, "Hello", 1).Return(...})
并得到:
GetSavingAccount(*context.valueCtx,uint64,uint64,string,int64)
0: &context.valueCtx{Context:(*context.valueCtx)(0xc000021290), key:grpc.streamKey{}, val:(*transport.Stream)(0xc000522100)}
...
The closest call I have is:
GetSavingAccount(*context.emptyCtx,uint64,uint64,string,int)
0: (*context.emptyCtx)(0xc00002a080)
...
GetSavingAccount 方法的方法定义是:
func (a *accountService) GetSavingAccount(ctx context.Context, customerID, id uint64, cardNo string, savingProductId int64) (*models.SavingAccount, error)
所以,你有方法:
GetSavingAccount(*context.Context,uint64,uint64,string,int64)
你还嘲笑过:
GetSavingAccount(*context.Context,uint64,uint64,string,int)
你最后一个参数不一样,你的问题是int64和int,所以你需要:
mockAccountService.On("GetSavingAccount", mock.Anything, a, a, "Hello", int64(1)).Return(...})
上下文参数总是使用mock.Anything,这比模拟上下文更容易。小心 int/int64/int32 和其他类型,也小心 pointer/struct 参数。
所以我在 golang 中使用 mockery and testify
进行单元测试测试代码如下:
const bufSize = 1024 * 1024
var lis *bufconn.Listener
var mockAccountService = &mocks.AccountService{}
func init() {
lis = bufconn.Listen(bufSize)
s := grpc.NewServer()
RegisterAccountManagementHandlerServer(s, &server{mockAccountService})
go func() {
if err := s.Serve(lis); err != nil {
log.Fatalf("Server exited with error: %v", err)
}
}()
}
func bufDialer(context.Context, string) (net.Conn, error) {
return lis.Dial()
}
func TestSayHello(t *testing.T) {
var a uint64 = 1
ctx := context.Background()
conn, err := grpc.DialContext(ctx, "bufnet", grpc.WithContextDialer(bufDialer), grpc.WithInsecure())
if err != nil {
t.Fatalf("Failed to dial bufnet: %v", err)
}
defer conn.Close()
client := NewAccountManagementHandlerClient(conn)
mockAccountService.On("GetSavingAccount", context.Background(), a, a, "Hello", 1).Return(&models.SavingAccount{
CustomerID: 1,
ID: 1,
CardNo: "Hello",
SavingProductID: 1,
Balance: 0,
Status: 1,
})
resp, err := client.GetSavingAccount(ctx, &GetSavingAccountDataRequest{
Id: 1,
CustomerId: 1,
CardNo: "Hello",
SavingProductId: 1,
})
if err != nil {
t.Fatalf("SayHello failed: %v", err)
}
fmt.Printf("Response: %+v", resp)
// Test for output here.
但是我得到这样的错误:
panic:
mock: Unexpected Method Call
-----------------------------
GetSavingAccount(*context.valueCtx,uint64,uint64,string,int64)
0: &context.valueCtx{Context:(*context.valueCtx)(0xc000115260), key:grpc.streamKey{}, val:(*transport.Stream)(0xc0004a2200)}
1: 0x1
2: 0x1
3: "Hello"
4: 1
The closest call I have is:
GetSavingAccount(mock.AnythingOfTypeArgument,uint64,uint64,string,int)
0: "&context.ValueCtx"
1: 0x1
2: 0x1
3: "Hello"
4: 1
我应该将什么值传递给 mock context.Background()
?
我试过mock.AnythingOfType("&context.emptyCtx")
,mock.Anything
,没用
谢谢
编辑:
我试过了
mockAccountService.On("GetSavingAccount", context.Background(), a, a, "Hello", 1).Return(...})
并得到:
GetSavingAccount(*context.valueCtx,uint64,uint64,string,int64)
0: &context.valueCtx{Context:(*context.valueCtx)(0xc000021290), key:grpc.streamKey{}, val:(*transport.Stream)(0xc000522100)}
...
The closest call I have is:
GetSavingAccount(*context.emptyCtx,uint64,uint64,string,int)
0: (*context.emptyCtx)(0xc00002a080)
...
GetSavingAccount 方法的方法定义是:
func (a *accountService) GetSavingAccount(ctx context.Context, customerID, id uint64, cardNo string, savingProductId int64) (*models.SavingAccount, error)
所以,你有方法:
GetSavingAccount(*context.Context,uint64,uint64,string,int64)
你还嘲笑过:
GetSavingAccount(*context.Context,uint64,uint64,string,int)
你最后一个参数不一样,你的问题是int64和int,所以你需要:
mockAccountService.On("GetSavingAccount", mock.Anything, a, a, "Hello", int64(1)).Return(...})
上下文参数总是使用mock.Anything,这比模拟上下文更容易。小心 int/int64/int32 和其他类型,也小心 pointer/struct 参数。