簡體   English   中英

swagger Golang 生成的 API 處理程序的 Mocking

[英]Mocking of API handler generated by swagger Golang

我真的需要一些幫助來測試我的 API 的行為,讓我解釋一下上下文:

此 API 使用存儲庫模式寫入 swagger 生成的 go 中。 在創建新 object 的情況下,我需要檢查數據庫中是否不存在該名稱,因此我調用存儲庫的 function 以在數據庫中按名稱獲取應用程序(見下文)

func (a *mongoApplicationRepository) GetApplicationByName(name string, ctx context.Context) (*models.Application, error) {
    _, span := otel.Tracer("GetApplicationByName").Start(ctx, "GetApplicationByName")
    defer span.End()

    var application models.Application

    err := a.mgConn.Collection("applications").
        FindOne(context.TODO(), bson.M{"name": name}).Decode(&application)

    if err != nil {
        if err == mongo.ErrNoDocuments {
            return &application, nil
        }
        return nil, err
    }
    return &application, nil
}

這個 function 由 api 處理程序調用,您可以在下面看到

type ApplicationCreateHandler struct {
    API       *operations.KubeesAPI
    repo      repo.ApplicationRepository
    statsRepo repo.StatsRepository
}

func NewApplicationCreateHandler(API *operations.KubeesAPI, repo repo.ApplicationRepository, statsRepo repo.StatsRepository) ApplicationCreateHandler {
    return ApplicationCreateHandler{
        API:       API,
        repo:      repo,
        statsRepo: statsRepo,
    }
}

// Handle is the HTTP handler for application creation
func (h *ApplicationCreateHandler) Handle(params application.AppCreateParams, principal *models.Principal) middleware.Responder {
    traceName := "application-create"
    ctx, span := otel.GetTracerProvider().Tracer(traceName).Start(context.TODO(), traceName)
    defer span.End()

    if params.Data == nil {
        err := "unable to validate input"
        logger().Errorln(err)
        return application.NewAppCreateBadRequest().WithPayload(&models.APIResponse{
            Msg: &err,
        })
    }

    if err := params.Data.Validate(h.API.Formats()); err != nil {
        err := fmt.Sprintf("unable to validate input: %v", err)
        logger().Errorln(err)
        return application.NewAppCreateBadRequest().WithPayload(&models.APIResponse{
            Msg: &err,
        })
    }

    app := models.Application{
        ID:       uuid.NewString(),
        Name:     params.Data.Name,
        Selector: params.Data.Selector,
    }

    c, err := h.repo.GetApplicationByName(*params.Data.Name, ctx)
    if err != nil {
        err := fmt.Sprintf("Unable to get Application: %v", err)
        logger().Errorln(err)
        return application.NewAppCreateInternalServerError().WithPayload(&models.APIResponse{
            Msg: &err,
        })
    }

    if c.ID != "" {
        r := "name already taken"
        logger().Errorln(r)
        return application.NewAppCreateInternalServerError().WithPayload(&models.APIResponse{
            Msg: &r,
        })
    }

    appDomain, err := app.ToDomainModel()
    if err != nil {
        err := fmt.Sprintf("Unable to convert application to domain model: %v", err)
        logger().Errorln(err)
        return application.NewAppCreateInternalServerError().WithPayload(&models.APIResponse{
            Msg: &err,
        })
    }

    err = h.repo.CreateApplication(appDomain, ctx)
    if err != nil {
        err := fmt.Sprintf("Unable to create Application: %v", err)
        logger().Errorln(err)
        return application.NewAppCreateInternalServerError().WithPayload(&models.APIResponse{
            Msg: &err,
        })
    }

    if err := h.statsRepo.UpdateApplicationsHistory(ctx); err != nil {
        err := fmt.Sprintf("unable to update applications history: %v", err)
        logger().Errorln(err)
        return application.NewAppCreateInternalServerError().WithPayload(&models.APIResponse{
            Msg: &err,
        })
    }

    return application.NewAppCreateCreated()
}

我只想檢查這種行為並測試是否我們已經有一個與新創建的應用程序相同的應用程序,這會引發錯誤而不是相反的情況。 但我不知道要模擬什么,因為存儲庫有一些外部依賴項

我強烈建議確保您的ApplicationCreateHandler只依賴於接口。 在這種情況下,您可以通過編寫模擬 class 或生成來模擬接口。 您可以by creating a new instance, and passing the mocked dependencies to it. Then execute the by creating a new instance, and passing the mocked dependencies to it. Then execute the Handle()` 方法並確保調用所有依賴項。

我強烈建議您生成模擬課程。 當您自己編寫模擬時,可能會在您的測試代碼中引入錯誤。 你不會想要的,對吧?

Mockgen 是mocking庫的一個很好的例子。 您可以按照他們的 github-readme 輕松安裝它。

腳步

  1. 為您的依賴項創建接口。
    最好在依賴接口的一側定義接口。 所以在你的情況下,這將在ApplicationCreateHandler文件中。 接口應該反映處理程序的需要。
type (
  ApplicationRepo interface {
    GetApplicationByName(name string, ctx context.Context)
    CreateApplication(domain Domain, ctx context.Context)
  }

  // other dependencies here... 

)
  1. 編寫單元測試
    創建一個新的單元測試
// youfile_test.go

func TestApplicationHandler(t *testing.T) {
  ctrl := gomock.NewController(t)
  defer ctrl.Finish()

  mockRepo := NewMockRepository(ctrl)
  mockRepo.EXPECT().
    Handle(gomock.any(), gomock.any()). // name, ctx
    Return(nil, nil).  // c, err
    Once()

  // other mocks...
  // mockApi
  // mockStatsRepo

  h := NewApplicationHandler(mockApi, mockStats, mockRepo)
  h.Handle(/*your test input*/)

  // do checks

}

如果mockRepo沒有被調用一次,測試會拋出錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM