首页 > 解决方案 > 你如何覆盖在 GoMock 中进行的调用?

问题描述

我正在尝试编写单元测试来模拟使用 GoMocks 进行的服务调用,这是一场真正的斗争。

我试图简化代码的一种方法是创建一个私有方法,该方法为所有模拟提供良好的响应,然后在每个需要模拟调用的不同响应的单独测试中(例如,测试模拟失败),我想要用不同的响应覆盖该调用。

例如,setupMocks fn(已擦洗)

func setupMocks(s *SSAdapterV1Suite, userId string) {
    s.mockDBDao.EXPECT().Mark(userId, gomock.Any()).
        Return(nil)
    s.mockDBDao.EXPECT().Get(userId).
        Return(userData, nil)
    s.mockDBDao.EXPECT().Delete(gomock.Any(), gomock.Any()).
        Return(nil)
}

当我在“成功”场景中使用 setupMocks fn 时,它工作正常。

但是,如果我尝试在另一个单元测试中使用它来测试如何处理服务调用中的错误,那么 gomocks 将使用 setupMocks fn 中的 mockResponse 设置,而不是我想要覆盖的那个。

是否有一个电话或我可以在 GoMocks 中做些什么来EXPECT()用其他东西覆盖模拟响应而不是附加callstack?

标签: unit-testinggomock

解决方案


在提供此功能的 GoMocks 代码中,我并没有真正看到任何类型的方法。

我看到的一种方法是您可以手动操作 gomock 控制器中的调用堆栈以尝试获得所需的内容。这可能比它的价值更复杂。幸运的是,我在查看此线程中的评论时发现了一个更简单的解决方法:https ://github.com/golang/mock/issues/137#issuecomment-440370200

你可以做的是在你调用 setupMocks() 之前调用你的覆盖。通过以相反的顺序进行覆盖,您将获得所需的效果。

例如,

func (s *SSAdapterV1Suite) DeleteFails_Returns500() {
    // Setup
    req := makeRequest()

    // Overrides need to go before setupMocks as a workaround for no mock override support.
    // This may change in the future (c.f., https://github.com/golang/mock/issues/137#issuecomment-440370200)
    expectedErrMsg := fmt.Errorf("Forced failure")
    s.mockDBDao.EXPECT().
        Delete(gomock.Any(), gomock.Any()).
        Return(expectedErrMsg)
    setupMocks(s, req.GetUserID())

    // Run
    resp, _ := s.server.RunTheThing(context.Background(), req)

    // Assert
    require.Equal(s.T(), int32(http.StatusInternalServerError), resp.GetStatus().GetCode())
    require.Equal(s.T(), "", resp.GetStatus().GetError())
}

请注意,创建模拟结构并将其连接到 ctrl 是在 SetupTests() fn 中完成的,并作为变量连接到 SSAdapterV1Suite。


推荐阅读