Golang 模拟上下文恐慌

Posted

技术标签:

【中文标题】Golang 模拟上下文恐慌【英文标题】:Golang mock context panic 【发布时间】:2020-10-23 00:26:54 【问题描述】:

所以我在 golang 中使用 mockery 和 testify 进行单元测试

测试代码如下:

const bufSize = 1024 * 1024

var lis *bufconn.Listener

var mockAccountService = &mocks.AccountService

func init() 
    lis = bufconn.Listen(bufSize)
    s := grpc.NewServer()
    RegisterAccountManagementHandlerServer(s, &servermockAccountService)
    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.valueCtxContext:(*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

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.valueCtxContext:(*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)

【问题讨论】:

如何注入“mockAccountService”供客户端使用? 请添加,添加GetSavingAccount方法的函数定义,查看参数和返回类型。而且,mock.Anything 适用于上下文,这应该是另一个问题,而不是上下文。
context.Background()context.Background()
@Flimzy 我试过你的建议,结果是我编辑的问题 @VasileRazdalovschi 我编辑我的问题,为 GetSavingAccount 方法添加函数定义并完成测试文件 【参考方案1】:

所以,你有方法:

GetSavingAccount(*context.Context,uint64,uint64,string,int64)

你已经嘲笑了:

GetSavingAccount(*context.Context,uint64,uint64,string,int)

你最后一个参数有区别,你的问题是int64int,所以你需要:

mockAccountService.On("GetSavingAccount", mock.Anything, a, a, "Hello", int64(1)).Return(...)

对于上下文参数总是使用mock.Anything,它比模拟上下文更容易。小心 int/int64/int32 和其他类型,还有指针/结构参数。

【讨论】:

@DimasAnggaSaputra 另外,如果你不喜欢 mock.Anything,你可以这样做: ctx := context.Background() service.Mock("method", ctx,...) 客户端。 Do(ctx, ...) 你会跳过这个模拟。任何东西,但它有点难看,取决于你的口味:)

以上是关于Golang 模拟上下文恐慌的主要内容,如果未能解决你的问题,请参考以下文章