-
Notifications
You must be signed in to change notification settings - Fork 378
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
FR: Matching maps with various type #388
Comments
This provides a Quality similar to `istanceOf` but also taking `Quality`s of subclasses of the given class. This is unsafe because there is no guarantee that the testee is actually of that subtype, but it may be required if the testee is a generic class. It solves issues like described in hamcrest/JavaHamcrest#388
This provides a Quality similar to `istanceOf` but also taking `Quality`s of subclasses of the given class. This is unsafe because there is no guarantee that the testee is actually of that subtype, but it may be required if the testee is a generic class. It solves issues like described in hamcrest/JavaHamcrest#388
This provides a Quality similar to `istanceOf` but also taking `Quality`s of subclasses of the given class. This is unsafe because there is no guarantee that the testee is actually of that subtype, but it may be required if the testee is a generic class. It solves issues like described in hamcrest/JavaHamcrest#388
This provides a Quality similar to `instanceOf` but also taking `Quality`s of subclasses of the given class. This is unsafe because there is no guarantee that the testee is actually of that subtype, but it may be required if the testee is a generic class. It solves issues like described in hamcrest/JavaHamcrest#388
I was looking at this issue, and I'm struggling to work out how to fix this. I tried to recreate the example as described above, but pulling out all the individual matchers so that I could inspect the exact types. Here's what I ended up with: public void testNestedMatchers() {
String k1 = "k1";
Map<String, String> v1 = Map.of(
"k11", "v11",
"k12", "v12");
String k2 = "k2";
List<String> v2 = List.of("v21", "v22");
String k3 = "k3";
String v3 = "v3";
Map<String, Object> actual = Map.of(
k1, v1,
k2, v2,
k3, v3
);
Matcher<? super String> k1Matcher = equalTo("k1");
assertThat(k1, k1Matcher);
Matcher<Map<? extends String, ?>> kv11Matcher = hasEntry("k11", "v11");
assertThat(v1, kv11Matcher);
Matcher<Map<? extends String, ?>> kv12Matcher = hasEntry("k12", "v12");
assertThat(v1, kv12Matcher);
Matcher<Map<? extends String, ? extends String>> v1Matcher = allOf(kv11Matcher, kv12Matcher);
assertThat(v1, v1Matcher);
Matcher<? super Map<? extends String, ?>> kv1Matcher = hasEntry(k1Matcher, v1Matcher);
// ^ error: incompatible types: inference variable V has incompatible bounds
// Matcher<? super Map<? extends String, ?>> kv1Matcher = hasEntry(k1Matcher, v1Matcher);
// ^
// upper bounds: Map<? extends String,? extends String>,Object
// lower bounds: Object
// where V,K are type-variables:
// V extends Object declared in method <K,V>hasEntry(Matcher<? super K>,Matcher<? super V>)
// K extends Object declared in method <K,V>hasEntry(Matcher<? super K>,Matcher<? super V>)
Matcher<Iterable<? extends String>> v2Matcher = contains("v21", "v22");
assertThat(v2, v2Matcher);
Matcher<Map<? extends String, ?>> kv2Matcher = hasEntry(equalTo("k2"), v2Matcher);
// ^ error: incompatible types: inference variable V has incompatible bounds
// Matcher<Map<? extends String, ?>> kv2Matcher = hasEntry(equalTo("k2"), v2Matcher);
// ^
// equality constraints: Object
// upper bounds: Iterable<? extends String>,Object
// where V,K are type-variables:
// V extends Object declared in method <K,V>hasEntry(Matcher<? super K>,Matcher<? super V>)
// K extends Object declared in method <K,V>hasEntry(Matcher<? super K>,Matcher<? super V>)
assertThat(actual, kv2Matcher);
Matcher<Map<? extends String, ?>> kv3Matcher = hasEntry("k3", "v3");
assertThat(actual, kv3Matcher);
Matcher<Map<? extends String, ?>> fullMatcher = allOf(kv1Matcher, kv2Matcher, kv3Matcher);
assertThat(actual, fullMatcher);
} Expanding out the types like this, I get the compilation errors as noted in the comments above. This is the definition of hasEntry: public static <K, V> Matcher<Map<? extends K, ? extends V>> hasEntry(Matcher<? super K> keyMatcher, Matcher<? super V> valueMatcher) {
return new IsMapContaining<>(keyMatcher, valueMatcher);
} To me, it looks like this is following the PECS rule (see https://stackoverflow.com/questions/2723397/what-is-pecs-producer-extends-consumer-super). In this instance, the method arguments are acting as consumers of values (hence the I recently put in a fix for the Does anyone have any suggestions? |
Given an actual map like this:
I wish/expect to make an assertion with matcher that looks like this:
But this fails with
The text was updated successfully, but these errors were encountered: