From 79e41a348b89775428ee87d0d112935e3c61abb0 Mon Sep 17 00:00:00 2001 From: Jakob Date: Thu, 27 Jan 2022 20:05:12 +0100 Subject: [PATCH] add pointer support to HaveField matcher (#495) --- matchers/have_field.go | 7 +++++++ matchers/have_field_test.go | 17 ++++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/matchers/have_field.go b/matchers/have_field.go index 2f1a91634..e1fe934d5 100644 --- a/matchers/have_field.go +++ b/matchers/have_field.go @@ -12,6 +12,13 @@ func extractField(actual interface{}, field string) (interface{}, error) { fields := strings.SplitN(field, ".", 2) actualValue := reflect.ValueOf(actual) + if actualValue.Kind() == reflect.Ptr { + actualValue = actualValue.Elem() + } + if actualValue == (reflect.Value{}) { + return nil, fmt.Errorf("HaveField encountered nil while dereferencing a pointer of type %T.", actual) + } + if actualValue.Kind() != reflect.Struct { return nil, fmt.Errorf("HaveField encountered:\n%s\nWhich is not a struct.", format.Object(actual, 1)) } diff --git a/matchers/have_field_test.go b/matchers/have_field_test.go index 5f63aea4f..0506600b9 100644 --- a/matchers/have_field_test.go +++ b/matchers/have_field_test.go @@ -9,9 +9,11 @@ import ( ) type Book struct { - Title string - Author person - Pages int + Title string + Author person + Pages int + Sequel *Book + Prequel *Book } func (book Book) AuthorName() string { @@ -54,6 +56,9 @@ var _ = Describe("HaveField", func() { DOB: time.Date(1802, 2, 26, 0, 0, 0, 0, time.UTC), }, Pages: 2783, + Sequel: &Book{ + Title: "Les Miserables 2", + }, } }) @@ -67,6 +72,7 @@ var _ = Describe("HaveField", func() { Entry("Top-level method", "AuthorName()", "Victor Hugo"), Entry("Nested method", "Author.DOB.Year()", BeNumerically("<", 1900)), Entry("Traversing past a method", "AbbreviatedAuthor().FirstName", Equal("Vic")), + Entry("Traversing a pointer", "Sequel.Title", "Les Miserables 2"), ) DescribeTable("negation works", @@ -78,6 +84,7 @@ var _ = Describe("HaveField", func() { Entry("Nested field", "Author.FirstName", "Hugo"), Entry("Top-level method", "AuthorName()", "Victor M. Hugo"), Entry("Nested method", "Author.DOB.Year()", BeNumerically(">", 1900)), + Entry("Traversing a pointer", "Sequel.Title", "Les Mis 2"), ) Describe("when field lookup fails", func() { @@ -117,6 +124,10 @@ var _ = Describe("HaveField", func() { success, err = HaveField("Author.Abbreviation", "Vic").Match(book) Ω(success).Should(BeFalse()) Ω(err.Error()).Should(ContainSubstring("HaveField could not find field named '%s' in struct:", "Abbreviation")) + + success, err = HaveField("Prequel.Title", "Les Miserables 0").Match(book) + Ω(success).Should(BeFalse()) + Ω(err.Error()).Should(ContainSubstring("HaveField encountered nil while dereferencing a pointer of type *matchers_test.Book.")) }) })