第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Go單元測試中stub和mock有什么區(qū)別?

Go單元測試中stub和mock有什么區(qū)別?

Go
HUX布斯 2023-05-08 17:47:25
我在 Go 的單元測試中使用模擬。Go的實現(xiàn)代碼中如何理解stub和mock的區(qū)別?
查看完整描述

1 回答

?
慕桂英4014372

TA貢獻1871條經(jīng)驗 獲得超13個贊

GO 中 mocks 和 stubs 的意圖與不同的編程語言相同:

  • 存根替代了代碼中將在測試執(zhí)行期間使用的某些依賴項。它通常是為一個特定的測試而構(gòu)建的,不太可能被重新用于另一個測試,因為它有硬編碼的期望和假設(shè)。

  • mock將存根提升到一個新的水平。它增加了配置方式,因此您可以為不同的測試設(shè)置不同的期望。這使得模擬更加復雜,但可重復用于不同的測試。

讓我們檢查一下它是如何工作的示例:

在我們的例子中,我們有 http 處理程序,它在內(nèi)部對另一個 Web 服務(wù)進行 http 調(diào)用。為了測試處理程序,我們希望將處理程序代碼與我們無法控制的依賴項(外部 Web 服務(wù))隔離開來。我們可以通過使用stub或來做到這一點mock

stub我們的處理程序代碼對于和是相同的mock。我們應該注入http.Client依賴關(guān)系以便能夠在單元測試中隔離它:

func New(client http.Client) http.Handler {

? ? return &handler{

? ? ? ? client: client,

? ? }

}


type handler struct {

? ? client http.Client

}


func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {

? ? ...

? ? // work with external web service that cannot be executed in unit test

? ? resp, err := h.client.Get("http://example.com")

? ? ...

}

我們對運行時的替代http.Client是直接的stub:


func TestHandlerStub(t *testing.T) {

? ? mux := http.NewServeMux()

? ? mux.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

? ? ? ? // here you can put assertions for request


? ? ? ? // generate response

? ? ? ? w.WriteHeader(http.StatusOK)

? ? }))

? ? server := httptest.NewServer(mux)


? ? r, _ := http.NewRequest(http.MethodGet, "https://some.com", nil)

? ? w := httptest.NewRecorder()

? ? sut := New(server.Client())

? ? sut.ServeHTTP(w, r)

? ? //assert handler response

}

模擬故事更復雜。我正在跳過模擬實現(xiàn)的代碼,但它的界面可能是這樣的:


type Mock interface {

? ? AddExpectation(path string, handler http.HandlerFunc)

? ? Build() *http.Client

}

這是使用 Mock 進行測試的代碼:


func TestHandlerMock(t *testing.T) {

? ? mock := NewMock()

? ? mock.AddExpectation("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

? ? ? ? // here you can put assertions for request


? ? ? ? // generate response

? ? ? ? w.WriteHeader(http.StatusOK)

? ? }))


? ? r, _ := http.NewRequest(http.MethodGet, "https://some.com", nil)

? ? w := httptest.NewRecorder()

? ? sut := New(mock.Build())

? ? sut.ServeHTTP(w, r)

? ? //assert handler response

}

對于這個簡單的示例,它沒有增加太多價值。但是想想更復雜的情況。您可以構(gòu)建更簡潔的測試代碼,并用更少的行覆蓋更多的案例。


如果我們必須調(diào)用 2 個服務(wù)并稍微改進我們的模擬,這就是測試設(shè)置的樣子:


mock.AddExpectation("/first", firstSuccesfullHandler).AddExpectation("/second", secondSuccesfullHandler)

mock.AddExpectation("/first", firstReturnErrorHandler).AddExpectation("/second", secondShouldNotBeCalled)

mock.AddExpectation("/first", firstReturnBusy).AddExpectation("/first", firstSuccesfullHandler)AddExpectation("/second", secondSuccesfullHandler)

您可以想象,如果我們沒有我們的微型模擬助手,您必須在測試中復制粘貼處理程序邏輯多少次。那些復制粘貼的代碼使我們的測試變得脆弱。


但是構(gòu)建自己的模擬并不是唯一的選擇。您可以依賴現(xiàn)有的模擬包,例如模擬 SQL 的DATA-DOG/go-sqlmock 。


查看完整回答
反對 回復 2023-05-08
  • 1 回答
  • 0 關(guān)注
  • 208 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號