testify
testify copied to clipboard
JSONEq returning error due to difference in ordering
The following snippet returns error:
require.JSONEq(t, `[
{"uid":"0x2","name@en":"pho\ton"},
{"uid":"0x1","name":"pho\ton"}
]`, `[
{"uid":"0x1","name":"pho\ton"},
{"uid":"0x2","name@en":"pho\ton"}
]`
)
Is there any work-around for this? This seems like a bug to me.
Json is unordered collection (see json.org)
Anyone have a workaround for this? This would be a really nice feature.
@yulicrunchy I've been working on a workaround for equating proto objects that have lists without a guaranteed order:
https://github.com/anz-bank/equals
it takes a generic interface, and converts it to json before doing any comparisons:
func TestStruct(t *testing.T) {
type Bar struct {
Arr []int
}
type Foo struct {
A Bar
}
ElementsMatchRec(t,
Foo{A: Bar{Arr: []int{1, 2, 3}}},
Foo{A: Bar{Arr: []int{3, 2, 1}}})
}
Json is unordered collection (see json.org)
In JSON, they take on these forms: An object is an unordered set ... An array is an ordered collection ...
from https://www.json.org/json-en.html
@roppa @black-desk maybe I'm misunderstanding your messages, but exactly because objects are unordered, OPs test should pass.
@roppa @black-desk maybe I'm misunderstanding your messages, but exactly because objects are unordered, OPs test should pass.
The OP's JSON blobs are both arrays, which are ordered, and the elements are in different orders, this is correctly failing.
I don't know why we're mentioning that JSON objects are unordered, it's not relevant to the OP's question. Perhaps we've all answered "that question" too many times and we missed that this is not an instance of "that question".
Anyone that would like to assert that two JSON arrays contain the same elements will need to first unmarshal them, like this:
func TestJSON(t *testing.T) {
var expected, actual []interface{}
require.NoError(t, json.Unmarshal([]byte(`[
{"uid":"0x2","name@en":"pho\ton"},
{"uid":"0x1","name":"pho\ton"}
]`), &expected))
require.NoError(t, json.Unmarshal([]byte(`[
{"uid":"0x1","name":"pho\ton"},
{"uid":"0x2","name@en":"pho\ton"}
]`), &actual))
require.ElementsMatch(t, expected, actual)
}
This is not a bug.
Pardon me, for some reason I thought the arrays in OPs post was indeed ordered. But yes, you're right. OPs test should fail.
String everything back to the normal
I don't want anything to fail
at least provide an option to ignore orders..
I don't want anything to fail
You and me both, buddy.
at least provide an option to ignore orders..
What would you call it? assert.JSONElementsMatch
I'd say no because ElementsMatch can only be called on slices and arrays. assert.JSONEqExeptWithArraysInAnyOrder
I'd say no because it's deliberately silly.
I did provide a sane example. I don't think this issue warrants any change. If you can describe a good change that would address this need then comment and I'll re-open.