Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add matcher for structs with ignored order in nested fields #71

Open
sebastianbuechler opened this issue Aug 28, 2023 · 2 comments
Open
Labels
enhancement New feature or request

Comments

@sebastianbuechler
Copy link

sebastianbuechler commented Aug 28, 2023

In PR golang/mock#546 we got a matcher that ignores the order of a slice or array. Sometimes the order can't be controlled properly it makes sense to have this matcher. But it is only capable of ignoring the order if the struct is of type slice or array, and not nested.

I would propose to add a matcher that will return true for unordered nested structs as well. Example unit test:

func TestOrderlessMatcher(t *testing.T) {
	testCases := []struct {
		expected interface{}
		value    interface{}
		matches  bool
	}{
		{
			struct{ List []string }{List: []string{"Value1", "Value2"}},
			struct{ List []string }{List: []string{"Value2", "Value1"}},
			true,
		},
	}
	for i, testCase := range testCases {
		t.Run(fmt.Sprintf("Test #%d", i), func(t *testing.T) {
			assert := assert.New(t)
			m := matchers.NewOrderlessMatcher(testCase.expected)
			assert.Equal(testCase.matches, m.Matches(testCase.value))
		})
	}
}
@r-hang
Copy link
Contributor

r-hang commented Aug 29, 2023

This is an understandable request. We are currently looking into whether or not the form of this feature should be a new top-level matcher or an option or change in the behavior of the existing InAnyOrder matcher.

@r-hang r-hang added the enhancement New feature or request label Sep 6, 2023
@abhipranay
Copy link

abhipranay commented Apr 14, 2024

@sebastianbuechler Can you clarify further about the matcher requirements ?

Can the struct have more fields which are not slice/array ? When you say nesting then do you mean any complex nested structure ?

eg:

type A struct {
  Field1 []string{}
  
  // some customer type which can have slice/array as it's own fields
  Field2 B

  // some primitive type fields
  Field3 int 
  
  // slice/array of some non primitive type
  Field4 []C
}

type B struct {
  Field1 []D
}

type C struct {
  Field1 int
}

type D struct {
  Field1 string
}

// so are you expecting structs mentioned below should match ?
A1 := A{
  Field1: { "1", "2" },
  Field2: B{
    Field1: []D{
      { Field1: "a" }
      { Field2: "b" }
    }
  },
  Field3: 4,
  Field4: []C{
    { Field1: 1 }
    { Field1: 2 }
  }
}

A2 := A{
  Field1: { "2", "1" },
  Field2: B{
    Field1: []D{
      { Field1: "b" }
      { Field2: "a" }
    }
  },
  Field3: 4,
  Field4: []C{
    { Field1: 1 }
    { Field1: 2 }
  }
}

One can always write a custom matcher for complex object but matching complex structs by ignoring order of slice in them can be helpful as many times using a slice is more appropriate to keep a collection. But slices have property to match only if all elements are equal with order , users end up writing customer matchers.

So having a matcher for complex structure which just works by ignoring any ordering in slice/array fields can be helpful if provided by library.

wdyt @r-hang ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants