在 golang 中进行集成测试时如何模拟外部 http 请求 api
How to mock external http request api when integration test in golang
我有获取数据库数据和从第三方获取其他数据的服务api。
像这样:
type Service interface {
GetDataFromDB(params apiParams, thirdClient ApiCient)
}
type Repository interface {
GetDataFromDB(orm *gorm.DB)
}
type DataService struct {
repo Repository
}
func (s *DataService) GetDataFromDB(params apiParams, thirdClient ApiClient) []interface{} {
var result []interface{}
dataFromDb := s.repo.GetDataFromDB()
dataFromAPI := thirdClient.Do(url)
result = append(result, dataFromDb)
result = append(result, dataFromAPI)
return result
}
func getData(c *gin.Context) {
//already implement interface
repo := NewRepository(orm)
srv := NewService(repo)
thirdPartyClient := NewApiClient()
params := ¶ms{Id:1,Name:"hello world"}
res := srv.GetDataFromDB(params, thirdPartyClient)
c.JSON(200,res)
}
func TestGetData(t *testing.T) {
w := httptest.NewRecorder()
request := http.NewRequest(http.MethodGet, "/v1/get_data", nil)
route.ServeHTTP(w, request)
}
而第三方api 客户端将return 随机数据。
遇到这种情况,我该怎么办?
如果我想模拟客户端以获得稳定的数据进行测试,如何在集成测试中伪造它?
我假设“集成测试”意味着您将 运行ning 整个应用程序,然后测试 运行ning 实例及其依赖项(在您的情况下是数据库和第三方服务).我假设你不是指单元测试。
对于集成测试,您有几种选择。就我而言,通常我会进行集成测试,包括第三方客户端连接的任何内容(无模拟),因为我想测试我的服务与第三方服务的集成。或者,如果这不可能,我可能会编写一个简单的存根应用程序,该应用程序具有与第三方服务相同的 public 接口,并在本地主机(或某处)上 运行 它,以便我的应用程序在测试期间连接到。
如果你不想或不能做其中任何一个并且想在你的 Go 应用程序中存根外部依赖,你可以为第三方客户端编写一个接口并提供该接口的存根实现当 运行ning 集成测试时(在你的应用程序上使用一个标志告诉它 运行 处于“存根”模式或类似的性质)。
这是一个可能看起来像的例子。这是您发布的源代码文件 - 但使用接口获取第三方数据:
type Service interface {
GetDataFromDB(params apiParams, thirdClient ApiCient)
}
type Repository interface {
GetDataFromDB(orm *gorm.DB)
}
type ThirdPartyDoer interface {
Do(url string) interface{}
}
type DataService struct {
repo Repository
thirdParty ThirdPartyDoer
}
func (s *DataService) GetDataFromDB(params apiParams, thirdClient ApiClient) []interface{} {
var result []interface{}
dataFromDb := s.repo.GetDataFromDB()
dataFromAPI := s.thirdParty.Do(url)
result = append(result, dataFromDb)
result = append(result, dataFromAPI)
return result
}
然后你可以为ThirdPartyDoer
编写一个存根实现,并在测试时使用它。当 运行 投入生产时,您可以使用真正的第三方客户端作为 ThirdPartyDoer
的实现:
type thirdPartyDoerStub struct {}
func (s *thirdPartyDoerStub) Do(url string) interface{} {
return "some static test data"
}
// ...
// Test setup:
integrationTestDataService := &DataService{repo: realRepository, thirdParty: &thirdPartyDoerStub{}}
// Production setup:
integrationTestDataService := &DataService{repo: realRepository, thirdParty: realThirdParty}
启动应用程序时,您需要在“测试设置”和“生产设置”之间设置 select 标志。
我有获取数据库数据和从第三方获取其他数据的服务api。
像这样:
type Service interface {
GetDataFromDB(params apiParams, thirdClient ApiCient)
}
type Repository interface {
GetDataFromDB(orm *gorm.DB)
}
type DataService struct {
repo Repository
}
func (s *DataService) GetDataFromDB(params apiParams, thirdClient ApiClient) []interface{} {
var result []interface{}
dataFromDb := s.repo.GetDataFromDB()
dataFromAPI := thirdClient.Do(url)
result = append(result, dataFromDb)
result = append(result, dataFromAPI)
return result
}
func getData(c *gin.Context) {
//already implement interface
repo := NewRepository(orm)
srv := NewService(repo)
thirdPartyClient := NewApiClient()
params := ¶ms{Id:1,Name:"hello world"}
res := srv.GetDataFromDB(params, thirdPartyClient)
c.JSON(200,res)
}
func TestGetData(t *testing.T) {
w := httptest.NewRecorder()
request := http.NewRequest(http.MethodGet, "/v1/get_data", nil)
route.ServeHTTP(w, request)
}
而第三方api 客户端将return 随机数据。
遇到这种情况,我该怎么办?
如果我想模拟客户端以获得稳定的数据进行测试,如何在集成测试中伪造它?
我假设“集成测试”意味着您将 运行ning 整个应用程序,然后测试 运行ning 实例及其依赖项(在您的情况下是数据库和第三方服务).我假设你不是指单元测试。
对于集成测试,您有几种选择。就我而言,通常我会进行集成测试,包括第三方客户端连接的任何内容(无模拟),因为我想测试我的服务与第三方服务的集成。或者,如果这不可能,我可能会编写一个简单的存根应用程序,该应用程序具有与第三方服务相同的 public 接口,并在本地主机(或某处)上 运行 它,以便我的应用程序在测试期间连接到。
如果你不想或不能做其中任何一个并且想在你的 Go 应用程序中存根外部依赖,你可以为第三方客户端编写一个接口并提供该接口的存根实现当 运行ning 集成测试时(在你的应用程序上使用一个标志告诉它 运行 处于“存根”模式或类似的性质)。
这是一个可能看起来像的例子。这是您发布的源代码文件 - 但使用接口获取第三方数据:
type Service interface {
GetDataFromDB(params apiParams, thirdClient ApiCient)
}
type Repository interface {
GetDataFromDB(orm *gorm.DB)
}
type ThirdPartyDoer interface {
Do(url string) interface{}
}
type DataService struct {
repo Repository
thirdParty ThirdPartyDoer
}
func (s *DataService) GetDataFromDB(params apiParams, thirdClient ApiClient) []interface{} {
var result []interface{}
dataFromDb := s.repo.GetDataFromDB()
dataFromAPI := s.thirdParty.Do(url)
result = append(result, dataFromDb)
result = append(result, dataFromAPI)
return result
}
然后你可以为ThirdPartyDoer
编写一个存根实现,并在测试时使用它。当 运行 投入生产时,您可以使用真正的第三方客户端作为 ThirdPartyDoer
的实现:
type thirdPartyDoerStub struct {}
func (s *thirdPartyDoerStub) Do(url string) interface{} {
return "some static test data"
}
// ...
// Test setup:
integrationTestDataService := &DataService{repo: realRepository, thirdParty: &thirdPartyDoerStub{}}
// Production setup:
integrationTestDataService := &DataService{repo: realRepository, thirdParty: realThirdParty}
启动应用程序时,您需要在“测试设置”和“生产设置”之间设置 select 标志。