重载静态导入

时间:2009-09-19 15:07:45

标签: java static-import

在测试课程中,我想提供自己的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)。”

4 个答案:

答案 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. 如果两个参数都为null,则返回true。
  2. 如果 expect 不为null,则在期望的上调用equals(),将 actual 作为参数传递。如果对象相等则返回true。
  3. 如果对象不相等,则抛出带有格式化消息的AssertionError。

答案 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不会受到奇怪的影响。未来的重新命名。