Add BeIdenticalTo matcher
This aims to address issue #104. This should be quite similar to
the BeSameInstanceAs matcher from Cedar, one of my personal favorites.
Internally it uses the == operator, and should positively match
primitive values as well as identical pointers to a value..
Tim Jarratt
8 years ago
0 | package matchers | |
1 | ||
2 | import ( | |
3 | "fmt" | |
4 | "runtime" | |
5 | ||
6 | "github.com/onsi/gomega/format" | |
7 | ) | |
8 | ||
9 | type BeIdenticalToMatcher struct { | |
10 | Expected interface{} | |
11 | } | |
12 | ||
13 | func (matcher *BeIdenticalToMatcher) Match(actual interface{}) (success bool, matchErr error) { | |
14 | if actual == nil && matcher.Expected == nil { | |
15 | return false, fmt.Errorf("Refusing to compare <nil> to <nil>.\nBe explicit and use BeNil() instead. This is to avoid mistakes where both sides of an assertion are erroneously uninitialized.") | |
16 | } | |
17 | ||
18 | defer func() { | |
19 | if r := recover(); r != nil { | |
20 | if _, ok := r.(runtime.Error); ok { | |
21 | success = false | |
22 | matchErr = nil | |
23 | } | |
24 | } | |
25 | }() | |
26 | ||
27 | return actual == matcher.Expected, nil | |
28 | } | |
29 | ||
30 | func (matcher *BeIdenticalToMatcher) FailureMessage(actual interface{}) string { | |
31 | return format.Message(actual, "to be identical to", matcher.Expected) | |
32 | } | |
33 | ||
34 | func (matcher *BeIdenticalToMatcher) NegatedFailureMessage(actual interface{}) string { | |
35 | return format.Message(actual, "not to be identical to", matcher.Expected) | |
36 | } |
0 | package matchers_test | |
1 | ||
2 | import ( | |
3 | "errors" | |
4 | ||
5 | . "github.com/onsi/ginkgo" | |
6 | . "github.com/onsi/gomega" | |
7 | . "github.com/onsi/gomega/matchers" | |
8 | ) | |
9 | ||
10 | var _ = Describe("BeIdenticalTo", func() { | |
11 | Context("when asserting that nil equals nil", func() { | |
12 | It("should error", func() { | |
13 | success, err := (&BeIdenticalToMatcher{Expected: nil}).Match(nil) | |
14 | ||
15 | Ω(success).Should(BeFalse()) | |
16 | Ω(err).Should(HaveOccurred()) | |
17 | }) | |
18 | }) | |
19 | ||
20 | It("should treat the same pointer to a struct as identical", func() { | |
21 | mySpecialStruct := myCustomType{} | |
22 | Ω(&mySpecialStruct).Should(BeIdenticalTo(&mySpecialStruct)) | |
23 | Ω(&myCustomType{}).ShouldNot(BeIdenticalTo(&mySpecialStruct)) | |
24 | }) | |
25 | ||
26 | It("should be strict about types", func() { | |
27 | Ω(5).ShouldNot(BeIdenticalTo("5")) | |
28 | Ω(5).ShouldNot(BeIdenticalTo(5.0)) | |
29 | Ω(5).ShouldNot(BeIdenticalTo(3)) | |
30 | }) | |
31 | ||
32 | It("should treat primtives as identical", func() { | |
33 | Ω("5").Should(BeIdenticalTo("5")) | |
34 | Ω("5").ShouldNot(BeIdenticalTo("55")) | |
35 | ||
36 | Ω(5.55).Should(BeIdenticalTo(5.55)) | |
37 | Ω(5.55).ShouldNot(BeIdenticalTo(6.66)) | |
38 | ||
39 | Ω(5).Should(BeIdenticalTo(5)) | |
40 | Ω(5).ShouldNot(BeIdenticalTo(55)) | |
41 | }) | |
42 | ||
43 | It("should treat the same pointers to a slice as identical", func() { | |
44 | mySlice := []int{1, 2} | |
45 | Ω(&mySlice).Should(BeIdenticalTo(&mySlice)) | |
46 | Ω(&mySlice).ShouldNot(BeIdenticalTo(&[]int{1, 2})) | |
47 | }) | |
48 | ||
49 | It("should treat the same pointers to a map as identical", func() { | |
50 | myMap := map[string]string{"a": "b", "c": "d"} | |
51 | Ω(&myMap).Should(BeIdenticalTo(&myMap)) | |
52 | Ω(myMap).ShouldNot(BeIdenticalTo(map[string]string{"a": "b", "c": "d"})) | |
53 | }) | |
54 | ||
55 | It("should treat the same pointers to an error as identical", func() { | |
56 | myError := errors.New("foo") | |
57 | Ω(&myError).Should(BeIdenticalTo(&myError)) | |
58 | Ω(errors.New("foo")).ShouldNot(BeIdenticalTo(errors.New("bar"))) | |
59 | }) | |
60 | }) |
21 | 21 | //It is an error for actual and expected to be nil. Use BeNil() instead. |
22 | 22 | func BeEquivalentTo(expected interface{}) types.GomegaMatcher { |
23 | 23 | return &matchers.BeEquivalentToMatcher{ |
24 | Expected: expected, | |
25 | } | |
26 | } | |
27 | ||
28 | //BeIdenticalTo uses the == operator to compare actual with expected. | |
29 | //BeIdenticalTo is strict about types when performing comparisons. | |
30 | //It is an error for both actual and expected to be nil. Use BeNil() instead. | |
31 | func BeIdenticalTo(expected interface{}) types.GomegaMatcher { | |
32 | return &matchers.BeIdenticalToMatcher{ | |
24 | 33 | Expected: expected, |
25 | 34 | } |
26 | 35 | } |