在参数匹配器中指定泛型类类型

时间:2012-02-13 15:50:23

标签: java generics jmock

考虑以下代码:

final Foo foo = context.mock(Foo.class);

context.checking(new Expectations() {{
    one(foo).someMethod(with(aNonNull(List.class)));
}});

我试图建议使用someMethod类型的非null参数调用List<Bar>。但是,我无法找出正确的语法来指定列表包含Bar类型的对象。以下简单的尝试不是有效的代码:

final Foo foo = context.mock(Foo.class);

context.checking(new Expectations() {{
    one(foo).someMethod(with(aNonNull(List<Bar>.class)));
}});

是否有正确的方法可以执行此操作,或者我是否被迫将@SuppressWarnings("unchecked")添加到我的测试方法中?

我很欣赏这不是严格意义上的JMock问题,但我认为我会将其标记为吸引那些可能在过去遇到此问题的人。

2 个答案:

答案 0 :(得分:2)

泛型信息在运行时被删除[JB] Effective Java SE p.l14。 所以你必须以另一种方式检查这个。

我发现这个方法来检查列表中所有元素的类型:

final Foo foo = context.mock(Foo.class);

context.checking(new Expectations() {{
    oneOf(foo).someMethod((List<Object>) with(Every.everyItem(IsInstanceOf.instanceOf(Bar.class))));
}});

答案 1 :(得分:0)

有一些方法至少可以集中抑制警告。例如,您可以继承Expectations

public static class UncheckedExpectations extends Expectations {
    @SuppressWarnings("unchecked")
    public <T, U extends T> U withUnchecked(Matcher<T> matcher) {
        return (U) super.with(matcher);
    }
}

然后使用其他方法:

context.checking(new UncheckedExpectations() {{
    one(foo).someMethod(withUnchecked(aNonNull(List.class)));
}});

这仍然是泛型的滥用,因为它在方法上使用了泛型类型参数,该参数实际上并未在参数中使用,而仅在不安全的强制转换中用于该方法。但是,它至少以不需要在整个代码中散布相同的抑制注释的方式来回避问题。

Hamcrest当然也可以使他们的with()方法像这样工作。他们没有,这有点遗憾,因为在使用该库的任何代码库中,关于Hamcrest代码的未经检查的警告都很常见。