Skip to content

Instantly share code, notes, and snippets.

@piksel
Created May 21, 2021 12:59
Show Gist options
  • Save piksel/84db751efeb7d00158eb57f4c05e988d to your computer and use it in GitHub Desktop.
Save piksel/84db751efeb7d00158eb57f4c05e988d to your computer and use it in GitHub Desktop.
HaveKeyValue gomega matcher
package metrics
import (
"fmt"
"github.com/onsi/gomega/format"
"github.com/onsi/gomega/matchers"
"github.com/onsi/gomega/types"
"reflect"
"strings"
)
// HaveKeyValueMatcher is a wrapper around matchers.HaveKeyWithValueMatcher that displays failures as:
// Expected
// map_key: actual_value
// to be
// map_key: expected_value
type HaveKeyValueMatcher struct {
matchers.HaveKeyWithValueMatcher
}
// HaveKeyValue is a wrapper around gomega.HaveKeyWithValue that displays failures as:
// Expected
// map_key: actual_value
// to be
// map_key: expected_value
//
// Example:
// Eventually(getMapWithResults).Should(SatisfyAll(
// HaveKeyValue("result", "ok"),
// HaveKeyValue("type", "message"),
// ))
//
// matchers.HaveKeyWithValueMatcher failure output:
// Expected
// <map[string]string | len:4>: {
// "foo": "random value",
// "bar": "another random value",
// "result": "OK",
// "type": "message",
// }
// to have {key: value}
// <map[interface {}]interface {} | len:1>: {
// "result": "ok",
// }
//
// HaveKeyValueMatcher failure output:
// Expected
// result: OK
// to be
// result: ok
func HaveKeyValue(key interface{}, value interface{}) types.GomegaMatcher {
return &HaveKeyValueMatcher{
matchers.HaveKeyWithValueMatcher{
Key: key,
Value: value,
},
}
}
// FailureMessage overrides the matchers.HaveKeyWithValueMatcher to display are more helpful message
func (matcher *HaveKeyValueMatcher) FailureMessage(actual interface{}) (message string) {
actType := reflect.TypeOf(actual)
keyType := reflect.TypeOf(matcher.Key)
valType := reflect.TypeOf(matcher.Value)
if actType.Kind() != reflect.Map || !actType.Key().AssignableTo(keyType) || !actType.Elem().AssignableTo(valType) {
var expected = reflect.MakeMap(reflect.MapOf(keyType, valType)).Interface()
return format.Message(actual, "to be", expected)
}
key := matcher.Key
expVal := matcher.Value
actVal := reflect.ValueOf(actual).MapIndex(reflect.ValueOf(key))
if !actVal.IsValid() {
actVal = reflect.New(valType).Elem()
}
indent := strings.Repeat(format.Indent, 1)
return fmt.Sprintf("Expected\n%s%s: %v\nto be\n%s%s: %v", indent, key, actVal, indent, key, expVal)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment