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

InstanceOf and raw types #155

Closed
dmfs opened this issue Dec 27, 2023 · 1 comment
Closed

InstanceOf and raw types #155

dmfs opened this issue Dec 27, 2023 · 1 comment
Labels
enhancement New feature or request

Comments

@dmfs
Copy link
Collaborator

dmfs commented Dec 27, 2023

In theory Confidence should be able to support something like hamcrest/JavaHamcrest#388, like this:

        Map<String, Object> actual = Map.of(
            "k1", Map.of(
                "k11", "v11",
                "k12", "v12"),
            "k2", List.of("v21", "v22"),
            "k3", "v3"
        );

        assertThat(actual, Core.<Map<String, Object>>allOf(
                containsEntry("k1", instanceOf(Map.class, allOf(
                    containsEntry("k11", "v11"),
                    containsEntry("k12", "v12"))
                )),
                containsEntry("k2", instanceOf(Iterable.class, iterates("v21", "v22"))),
                containsEntry("k3", instanceOf(String.class, equalTo("v3")))
            )
        );

The problem, however, is, that instanceOf does not play well with raw types but we can't pass a Class instance of a generic type (because there is no such thing). The problem is that a generic Map type is never a supertype of a raw type.

Changing the InstanceOf constructor from

    public <V extends T> InstanceOf(Class<V> expectation, Quality<? super V> delegate)

to

    public <V extends T, Q extends V> InstanceOf(Class<V> expectation, Quality<? super Q> delegate)

indeed fixes the issue because you can now pass a Quality for any subtype of V but that's not really type safe anymore because there is no guarantee that the tested instance is indeed a Q .

This would compile now (it doesn't without this change) but the test would fail with a ClassCastException

    static class C1 {
        int foo() {
            return 1;
        }
    }
    
    static class C2 extends C1 {
        int bar() {
            return 2;
        }
    }
    
    @Test
    void instanceOfTest()
    {
        Object o = new C1();
        assertThat(o, instanceOf(C1.class, has(C2::bar, equalTo(2))));
    }

This needs to be considered carefully because it's not possible to achieve both, supporting instanceOf with raw types and type safe casting, at the same time.

@dmfs dmfs added the enhancement New feature or request label Dec 27, 2023
@dmfs
Copy link
Collaborator Author

dmfs commented Dec 27, 2023

we could add another Quality called something like unsafeInstanceOf that supports this case but makes it clear that the type-safety guarantees are very weak.

dmfs added a commit that referenced this issue Dec 28, 2023
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.
dmfs added a commit that referenced this issue Dec 28, 2023
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
dmfs added a commit that referenced this issue Dec 28, 2023
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
dmfs added a commit that referenced this issue Dec 28, 2023
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
@dmfs dmfs closed this as completed in 15c8981 Dec 28, 2023
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

1 participant