import java.util.Collection;
import java.util.List;
import java.util.function.Supplier;

class Should {

    static void beEqual(Object expected, Object given) {
        if (!expected.equals(given)) {
            throw new RuntimeException("equality failed. expected " + expected + ", but given " + given);
        }
    }
}

// ----------------------------------------------------------------

class A {

    String description() {
        return "A";
    }
}

class ASpec {

    void runAll(Collection<Supplier<? extends A>> implementations) {
        implementations.forEach(this::run);
    }

    void run(Supplier<? extends A> impl) {
        should_be_A_object_description(impl.get());
    }

    private String descriptionOf(A a) {
        return a.getClass().getSimpleName();
    }

    void should_be_A_object_description(A a) {
        final var expected = descriptionOf(a);
        Should.beEqual(expected, a.description());
    }
}

class B extends A {

    String description() {
        return "B";
    }
}

class Ideone {

    public static void main(String[] args) {
        new ASpec().runAll(List.of(A::new, B::new));
    }
}