2016-08-05 84 views
4

我正在使用JUnit 4.12。 assert方法本质上不是通用的。例如,assertEquals方法看起来像:为什么JUnit声明方法不是Java中的通用方法?

static public void assertEquals(Object expected, Object actual) {..} 

为什么不是这样?

static public <T> void assertEquals(T expected, T actual) {..} 

我觉得需要更好的编译时检查和IDE自动完成的泛型方法声明。

+0

Downvoters,请提供原因。 –

+0

泛型给你带来了什么?请参阅[我对这个问题的回答](http://stackoverflow.com/a/38475261/3788176),它解释了为什么它是多余的。 –

+0

@AndyTurner这样我就不会无意中比较两种不同类型的对象,而这些对象无论如何都是无效的。 IDE将提供更好的建议,以便可以在方法中传递哪些参数,而不是显示范围中所有现有对象的列表。 –

回答

5

有了这样一个通用的方法:

<T> void assertEquals(T expected, T actual) { /* ... */ } 

让你没有类型安全,避免不同类型的比较:您可以在任何通过此方法,因为T退化为它的上限,Object

assertEquals("string", 0); // Compiles fine, even though they can't be equal. 

Ideone demo

而且你也不可以使用expected任何方法和actualObject上找不到。所以,T基本上只是Object

因此,添加泛型只是过度复杂的实现。现在


,你可以这样定义一个类:

class GenericAssert<T> { 
    void assertEquals(T expected, T actual) { /* ... */ } 
} 

,你可以使用此类似:

new GenericAssert<String>().assertEquals("string", 0); // Compiler error. 

,因为你现在已经置于更严格的上界在课堂上,可接受的参数为assertEquals

但这只是感觉有点尴尬。

+0

谢谢。我实施了它,我看到你所说的是正确的。我需要更好地理解泛型。 –

+0

GenericAssert可以解决我的目的。但我确实发现它会使测试用例变得更加混乱,因为与使用JUnit中声明的干净静态方法相比,我需要为不同类型的对象使用不同的GenericAsset对象。谢谢你的时间! –

+0

或者,您可以编写'checkedAssertEquals(Object,Object)'方法,检查参数是否兼容,然后调用'Assert.assertEquals'。它不会在编译时失败,但是一旦测试运行就会失败,这并不是那么糟糕。 –

2

你想看看assertThat和Hamcrest匹配器;

assertThat(String reason, T actual, Matcher<? super T> matcher) 

所以:如assertThat实际上泛型工作

assertEquals("abc", 123); 

编译,但失败;而

assertThat(123, is("abc")); 

甚至不会编译!

而且我甚至没有提到asser那些电话是更好的阅读;并在失败时提供更好的信息。你甚至可以使用它们来比较地图,集合等等。

长话短说:只有一个断言,任何人需要 - 断言那那就是!

+0

谢谢。我尝试使用这个,但它的编译没有任何错误! –

+0

那么,我的编译器给我:'方法assertThat(T,Matcher )在类型Assert不适用于参数(字符串,匹配)'......不知道你在做什么,以不击中错误在那里。 – GhostCat

+0

那么,我用org.junit.Assert.assertThat和org.hamcrest.CoreMatchers.is,并没有给出任何编译时错误。 –

相关问题