在测试课程中,我想提供自己的assertEquals
重载,其中包含一些不依赖于Object.equals
的特殊逻辑。不幸的是,这不起作用,因为只要我在本地声明我的assertEquals
方法,Java就不再从org.junit.Assert.*
找到静态导入。
有解决方法吗?即有没有办法为静态导入的方法提供额外的重载? (相当明显的解决方案是以不同的方式命名方法,但此解决方案不具有相同的美学吸引力。)
我的测试类文件如下所示:
package org.foo.bar;
import static org.junit.Assert.*;
import org.junit.Test;
public class BarTest {
private static void assertEquals(Bar expected, Bar other) {
// Some custom logic to test equality.
}
@Test
public void testGetFoo() throws Exception {
Bar a = new Bar();
assertEquals(42, a.getFoo()); // Error *
}
@Test
public void testCopyConstructor() throws Exception {
Bar a = new Bar();
// Fill a.
Bar b = new Bar(a);
assertEquals(a, b);
}
}
Error *
是“assertEquals(Bar, Bar)
类型中的方法BarTest
不适用于参数(int, int)
。”
答案 0 :(得分:3)
这个答案有两个部分 - 一个关于编译错误,另一个关于assertEquals()的用法
问题是在两个不同的命名空间中有两个assertEquals()方法 - 一个存在于org.junit.Assert命名空间中,另一个存在于org.foo.bar.BarTest命名空间(当前命名空间)中。 p>
由于shadowing rules declared in the Java Language Specification,编译器会报告错误。 Assert.assertEquals()的静态导入被BarTest类中声明的assertEquals()遮蔽。
修复(总是在镜像声明的情况下)是使用FQN(完全限定名称)。如果您打算使用JUnit Assert类的assertEquals(...),请使用
org.junit.Assert.assertEquals(...)
当您需要使用声明时,只需使用
即可assertEquals(...)
仅在BarTest中的,它被遮蔽。在只需要Assert.assertEquals()或BarTest.asserEquals()的所有其他类中,您可以导入Assert或BarTest(我认为您不需要在其他地方导入BarTest,但仍然说明了这一点。)
当没有阴影时,您可以简单地导入类或静态方法,并在没有FQN的情况下使用它。
要考虑的其他内容
Assert.assertEquals()在内部使用参数类的equals()方法。在测试用例中声明assertEquals()违反了DRY原则,因为类型的equals()方法应该被实现并且一致地使用 - 在源代码中放置两个不同的实现并且在单元测试中必然会引起混淆。 / p>
最好的方法是在Bar上实现equals(),然后在测试用例中使用Assert.assertEquals()。如果您已经拥有,则不需要BarTest.assertEquals()。 assertEquals()的伪代码有点像下面的
答案 1 :(得分:3)
在单元测试中调用assertEquals(Bar, Bar)
的具体示例的一种可能解决方案是使用提供静态方法的类扩展类,如下所示:
class BarAssert extends Assert {
public static void assertEquals(Bar expected, Bar other) {
// Some custom logic to test equality.
}
}
然后,您可以加入import static BarAssert.assertEquals;
并使用自定义逻辑。
道歉,这并没有直接回答这个问题,更多的是针对你的例子。根据我对该问题的评论,我建议不要采用这种方法。
答案 2 :(得分:1)
唯一的方法是完全符合其中一项。
import static org.junit.Assert.*;
import org.junit.Test;
public class BarTest {
private static void assertEquals(Bar expected, Bar other) {
// Some custom logic to test equality.
}
@Test
public void testGetFoo() throws Exception {
Bar a = new Bar();
org.junit.Assert.assertEquals(42, a.getFoo());
}
}
答案 3 :(得分:0)
this.assertEquals(a,b);
或
BarTest.assertEquals(a,b);
我会选择第一个,因为尽管它是一个静态方法,你必须有一个实例来使用它(它是私有的)而且this
不会受到奇怪的影响。未来的重新命名。