go - 有没有办法擦除响应编写器中的数据?
问题描述
我正在为 elasticsearch 中间件编写测试,我正在使用一个函数来构建测试服务器,在该服务器中,我为每个测试传递一个配置结构片段,并在一个处理函数中对其进行迭代,并将预期的响应写入响应编写器. 这是我的功能。
func newMockClient(url string) (*elasticsearch, error) {
client, err := elastic.NewSimpleClient(elastic.SetURL(url))
if err != nil {
return nil, fmt.Errorf("error while initializing elastic client: %v", err)
}
es := &elasticsearch{
url: url,
client: client,
}
return es, nil
}
type ServerSetup struct {
Method, Path, Body, Response string
HTTPStatus int
}
func buildTestServer(t *testing.T, setups []*ServerSetup) *httptest.Server {
handlerFunc := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
requestBytes, _ := ioutil.ReadAll(r.Body)
requestBody := string(requestBytes)
matched := false
for _, setup := range setups {
if r.Method == setup.Method && r.URL.EscapedPath() == setup.Path {
matched = true
if setup.HTTPStatus == 0 {
w.WriteHeader(http.StatusOK)
} else {
w.WriteHeader(setup.HTTPStatus)
}
_, err := w.Write([]byte(setup.Response))
if err != nil {
t.Fatalf("Unable to write test server response: %v", err)
}
}
}
if !matched {
t.Fatalf("No requests matched setup. Got method %s, Path %s, body %s", r.Method, r.URL.EscapedPath(), requestBody)
}
})
return httptest.NewServer(handlerFunc)
}
它是从 复制的github.com/github/vulcanizer
。当我使用它运行单个测试时,它工作正常。例如这个测试
func TestCreateIndex(t *testing.T) {
setup := &ServerSetup{
Method: "PUT",
Path: "/test",
Response: `{"acknowledged": true, "shards_acknowledged": true, "index": "test"}`,
}
ts := buildTestServer(t, []*ServerSetup{setup})
es, _ := newMockClient(ts.URL)
err := es.createIndex(context.Background(), "test", nil)
if err != nil {
t.Fatalf("Index creation failed with error: %v\n", err)
}
}
但是当我尝试在像这样的单个测试中检查不同的行为时,我得到了一个错误http: multiple response.WriteHeader calls
func TestDeleteIndex(t *testing.T) {
setup := &ServerSetup{
Method: "DELETE",
Path: "/test",
Response: `{"acknowledged": true}`,
}
errSetup := &ServerSetup{
Method: "DELETE",
Path: "/test",
Response: `{"acknowledged": false}`,
}
ctx := context.Background()
ts := buildTestServer(t, []*ServerSetup{setup, errSetup})
defer ts.Close()
es, _ := newMockClient(ts.URL)
err := es.deleteIndex(ctx, "test")
if err != nil {
t.Fatalf("Index creation failed with error: %v\n", err)
}
err = es.deleteIndex(ctx, "test")
if err == nil {
t.Fatal("Expected error but not found")
}
}
我猜这是因为当我第二次运行 deleteIndex 时,它再次 ping 服务器但响应编写器已经被写入,所以它不能向它写入任何其他内容。
无论如何我可以在我的处理函数开始时检查一下
handlerFunc := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if w != nil{
// clear data in response writer
}
// .........
}
解决方案
我不认为你正在做的是测试你的功能的正确方法。您需要将测试与测试用例分开,以检查不同的行为:
func Test_DeleteIndex(t *testing.T) {
t.Run("Should be ok with correct setup", func(t *testing.T) {
setup := &ServerSetup{
Method: "DELETE",
Path: "/test",
Response: `{"acknowledged": true}`,
}
ctx := context.Background()
ts := buildTestServer(t, []*ServerSetup{setup})
defer ts.Close()
es, _ := newMockClient(ts.URL)
err := es.deleteIndex(ctx, "test")
require.NoError(t, err)
})
t.Run("Shouldn't be ok with wrong setup", func(t *testing.T) {
setup := &ServerSetup{
Method: "DELETE",
Path: "/test",
Response: `{"acknowledged": false}`,
}
ctx := context.Background()
ts := buildTestServer(t, []*ServerSetup{setup})
defer ts.Close()
es, _ := newMockClient(ts.URL)
err := es.deleteIndex(ctx, "test")
require.Error(t, err)
})
}
推荐阅读
- c# - 启动进程 WMI 在另一台计算机上最大化
- oracle - Oracle Apex 交互式报表标题过滤器大小
- python - cv2.VideoCapture(0) 似乎以蜗牛的速度停止我的程序
- python - 使用 virtualenv 嵌入 python 和 pybind11
- powershell - Powershell 5.1:如何显示集群中每个节点的IP地址?
- angular - 引导选择中的选定值
- mysql - (Spring JPA) 方法名查询
- multithreading - 如何在 java/groovy 中进行并行异步/解除阻塞 http post 调用
- python - 如何为相同的功能模拟不同的?
- linux - 错误的类型参数:/var/lib/gems/2\.5\.0