Pact在Go中的消费者测试。dsl.Match函数存在问题。

huangapple go评论82阅读模式
英文:

Pact consumer test in Go. Issue with dsl.Match function

问题

我正在使用Go编写一个Pact消费者测试。当我定义交互时,我需要添加预期的响应对象。提供者服务是用PHP编写的,这是我期望的响应:

return  [
            'status' => 'success',
            'data' => [
                'configuration' => Associative Array,
                'undeploy_configuration' => Associative Array,
                'meta_data' => Associative Array,
                'undeploy_lora_app_key' => String,
            ],
        ];

这是我在Go中创建的表示应该获得的响应的对象:

deviceConfigurationResponse := dsl.Like(map[string]interface{}{
		"status": "success",
		"data": dsl.Like(map[string]interface{}{
			"configuration": dsl.MapMatcher{
				"config1": dsl.String("value1"),
				"config2": dsl.String("value2"),
			},
			"undeploy_configuration": dsl.MapMatcher{
				"undeploy1": dsl.String("value3"),
				"undeploy2": dsl.String("value4"),
			},
			"meta_data": dsl.MapMatcher{
				"meta1": dsl.String("info1"),
				"meta2": dsl.String("info2"),
			},
			"undeploy_lora_app_key": dsl.String("example_undeploy_lora_app_key"),
		}),
	})

然而,当我运行测试时,我得到以下错误:

--- FAIL: TestGetDeviceConfiguration (1.79s)
panic: match: unhandled type: interface {} [recovered]
        panic: match: unhandled type: interface {}

这是完整的代码:

func TestGetDeviceConfiguration(t *testing.T) {
	// Create Pact client
	pact := &dsl.Pact{
		Consumer: "consumer",
		Provider: "provider",
		PactDir:  "./pacts",
	}

	defer pact.Teardown()

	deviceConfigurationResponse := dsl.Like(map[string]interface{}{
		"status": "success",
		"data": dsl.Like(map[string]interface{}{
			"configuration": dsl.MapMatcher{
				"config1": dsl.String("value1"),
				"config2": dsl.String("value2"),
			},
			"undeploy_configuration": dsl.MapMatcher{
				"undeploy1": dsl.String("value3"),
				"undeploy2": dsl.String("value4"),
			},
			"meta_data": dsl.MapMatcher{
				"meta1": dsl.String("info1"),
				"meta2": dsl.String("info2"),
			},
			"undeploy_lora_app_key": dsl.String("example_undeploy_lora_app_key"),
		}),
	})

	// Define the expected interaction with the provisioning-service
	value := "123456789"
	pact.
		AddInteraction().
		Given("Device configuration exists for the given device ID").
		UponReceiving("A request to get device configuration").
		WithRequest(dsl.Request{
			Method:  "GET",
			Path:    dsl.String(fmt.Sprintf("/api/prov/state/%s/configuration", value)),
			Headers: dsl.MapMatcher{"Accept": dsl.String("application/json")},
		}).
		WillRespondWith(dsl.Response{
			Status:  200,
			Headers: dsl.MapMatcher{"Content-Type": dsl.String("application/json")},
			Body:    dsl.Match(deviceConfigurationResponse),
		})

	// Test the OnSessionEstablished function
	var test = func() error {
		cache := new(CacheMock)
		deviceConfigGetter := new(DeviceConfigGetterMock)

		_, err := GetDeviceConfiguration(value)

		cache.AssertExpectations(t)
		deviceConfigGetter.AssertExpectations(t)

		return err
	}

	// Verify the interaction with the provider
	var err = pact.Verify(test)
	assert.NoError(t, err)
}
英文:

I am writing a Pact consumer test in Go. When I define the interaction I need to add the expected response object. The provider service is written in PHP and this is the response I am expecting:

return  [
            'status' => 'success',
            'data' => [
                'configuration' => Associative Array,
                'undeploy_configuration' => Associative Array,
                'meta_data' => Associative Array,
                'undeploy_lora_app_key' => String,
            ],
        ];

This is the object I created in Go to represent the response I should get:

deviceConfigurationResponse := dsl.Like(map[string]interface{}{
		"status": "success",
		"data": dsl.Like(map[string]interface{}{
			"configuration": dsl.MapMatcher{
				"config1": dsl.String("value1"),
				"config2": dsl.String("value2"),
			},
			"undeploy_configuration": dsl.MapMatcher{
				"undeploy1": dsl.String("value3"),
				"undeploy2": dsl.String("value4"),
			},
			"meta_data": dsl.MapMatcher{
				"meta1": dsl.String("info1"),
				"meta2": dsl.String("info2"),
			},
			"undeploy_lora_app_key": dsl.String("example_undeploy_lora_app_key"),
		}),
	})

However when I run the test I get this error:

--- FAIL: TestGetDeviceConfiguration (1.79s)
panic: match: unhandled type: interface {} [recovered]
        panic: match: unhandled type: interface {}

This is the full code:

func TestGetDeviceConfiguration(t *testing.T) {
	// Create Pact client
	pact := &dsl.Pact{
		Consumer: "consumer",
		Provider: "provider",
		PactDir:  "./pacts",
	}

	defer pact.Teardown()

	deviceConfigurationResponse := dsl.Like(map[string]interface{}{
		"status": "success",
		"data": dsl.Like(map[string]interface{}{
			"configuration": dsl.MapMatcher{
				"config1": dsl.String("value1"),
				"config2": dsl.String("value2"),
			},
			"undeploy_configuration": dsl.MapMatcher{
				"undeploy1": dsl.String("value3"),
				"undeploy2": dsl.String("value4"),
			},
			"meta_data": dsl.MapMatcher{
				"meta1": dsl.String("info1"),
				"meta2": dsl.String("info2"),
			},
			"undeploy_lora_app_key": dsl.String("example_undeploy_lora_app_key"),
		}),
	})

	// Define the expected interaction with the provisioning-service
	value := "123456789"
	pact.
		AddInteraction().
		Given("Device configuration exists for the given device ID").
		UponReceiving("A request to get device configuration").
		WithRequest(dsl.Request{
			Method:  "GET",
			Path:    dsl.String(fmt.Sprintf("/api/prov/state/%s/configuration", value)),
			Headers: dsl.MapMatcher{"Accept": dsl.String("application/json")},
		}).
		WillRespondWith(dsl.Response{
			Status:  200,
			Headers: dsl.MapMatcher{"Content-Type": dsl.String("application/json")},
			Body:    dsl.Match(deviceConfigurationResponse),
		})

	// Test the OnSessionEstablished function
	var test = func() error {
		cache := new(CacheMock)
		deviceConfigGetter := new(DeviceConfigGetterMock)

		_, err := GetDeviceConfiguration(value)

		cache.AssertExpectations(t)
		deviceConfigGetter.AssertExpectations(t)

		return err
	}

	// Verify the interaction with the provider
	var err = pact.Verify(test)
	assert.NoError(t, err)
}

答案1

得分: 1

你正在使用的方法(Match)接受一个带有结构标签的结构体(请参阅https://github.com/pact-foundation/pact-go#auto-generate-matchers-from-struct-tags),这些标签指定了结构体内各个项应该如何匹配。你已经手动提供了一个带有正确匹配器的结构体,所以根本不需要将其包装在Match中。

像这样的代码应该可以工作:

        WillRespondWith(dsl.Response{
            Status:  200,
            Headers: dsl.MapMatcher{"Content-Type": dsl.String("application/json")},
            Body:    deviceConfigurationResponse,
        })
英文:

The method you are using (Match) takes a struct annotated with struct tags (see https://github.com/pact-foundation/pact-go#auto-generate-matchers-from-struct-tags) that specify how the various items within the struct should be matched. You are manually providing a structure with the right matchers already, so there is no need to wrap it in Match at all.

Something like this should work:

        WillRespondWith(dsl.Response{
            Status:  200,
            Headers: dsl.MapMatcher{"Content-Type": dsl.String("application/json")},
            Body:    deviceConfigurationResponse,
        })

huangapple
  • 本文由 发表于 2023年4月6日 00:02:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/75941670.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定