Java 抽象类保护方法junit测试用例

Java 抽象类保护方法junit测试用例,java,junit,Java,Junit,以代码为例: abstract public class TigerFinderPage extends TigerPage private Manager manager; protected Manager getTiger() { // If we haven't already done so, get the tiger. if (tiger== null) { try { tiger= EntityResolution.ge

以代码为例:

abstract public class TigerFinderPage extends TigerPage
private Manager manager;
protected Manager getTiger()
{
    //  If we haven't already done so,  get the tiger.
    if (tiger== null) {
        try {
            tiger= EntityResolution.getTigerFromName(ResTools.resolveNoTranslation(getConfigBundle(), "tiger", ""));
        } catch (Exception e) {
            LogTools.error(logger, null, e);
            return null;
        }
    }
    return tiger;
}
尝试1:

public class TigerFinderPageTest {

private TigerFinderPage tigerFinderPage;

@Before
public void setUp() throws Exception {

    TigerFinderPage = new TigerFinderPage () {
        @Override
        protected ResourceProvider getBundle() {
            return null;
        }

        @Override
        protected ResourceProvider getConfigBundle() {
            return null;
        }
    };
}

@Test
public void testTigerManager(){
    assertNull(tigerFinderPage.getTiger());
}
}

当受保护的方法在不同的包中时,如何测试它们?我已经尝试过使用反射,但不知道如何在这种情况下实现它。

一个答案是遵循JUnit的最佳实践,将生产代码和测试代码都放在同一个包中,以便允许访问受保护的成员,但访问不同源文件夹中的成员,因此,非生产代码不会干扰生产代码。例如,在maven的结构中:

-- src
   +-- main
       +-- java
           +-- org
               +-- mypackage # Production code for org.mypackage
   +-- test
       +-- java
           +-- org
               +-- mypackage # Testing code for org.mypackage
如果这不是一个选项,您可以从抽象类继承并增加所述方法的可见性,以便测试可以访问它:

public class TigerFinderPageTest {        
    public static class TigerFinderPageDummy extends TigerFinderPage {
        @Override
        protected ResourceProvider getBundle() {
            return null;
        }

        @Override
        protected ResourceProvider getConfigBundle() {
            return null;
        }

        /** Note this method is PUBLIC */
        @Override
        public Manager getTiger() {
            return super.getTiger();
        }
    }

    private TigerFinderPageDummy tigerFinderPage;

    @Before
    public void setUp() throws Exception {
        tigerFinderPage = new TigerFinderPageDummy();
    }

    @Test
    public void testTigerManager(){
        assertNull(tigerFinderPage.getTiger());
    }
}

测试非公共成员会将您的测试与您的实现联系起来,从而使重构变得更加困难

如果它足够重要以至于不能通过公共接口进行测试,那么它必须是独立的功能,可以存在于自己的类中

在本例中,我将为
LazyTigerFactory
创建一个单独的类和测试:

public final class LazyTigerFactory {
    private Manager manager;
    public Manager getTiger()
    {
        //  If we haven't already done so,  get the tiger.
        if (tiger == null) {
            try {
                tiger= EntityResolution.getTigerFromName(ResTools.resolveNoTranslation(getConfigBundle(), "tiger", ""));
            } catch (Exception e) {
                LogTools.error(logger, null, e);
                return null;
            }
        }
        return tiger;
    }
}
然后在课堂上使用它:

abstract public class TigerFinderPage extends TigerPage
    private final LazyTigerFactory tigerFactory = new LazyTigerFactory();
    protected Manager getTiger(){
       return tigerFactory.getTiger();
    }
利益
  • 您可以在工厂测试的创建过程中获得完整的测试覆盖率,而不会使
    TigerFinderPage
    测试变得混乱
  • 您可以在以后轻松地将
    LazyTigerFactory
    更改为另一个
  • TigerFinderPage
    具有较少的直接依赖关系
  • TigerFinderPage
    更小,更不懒惰,更不凌乱这个类的真正功能(它的单一职责)
  • 您甚至可以更改为注入一个完全解耦的工厂接口,这可能有助于其他测试

当我执行notNull时,你所说的
是什么意思?
ResTools.ResolveNotTranslation
做什么?不清楚创建
Tiger
实例所需的信息来自何处。
ResTools.ResolveNotTranslation
与此无关,它只是将管理器转换为西班牙语或西班牙语的实现。如果您试图测试受保护的方法,请使用反射。检查这里-如果
getConfigBundle
返回
null
,那么将使用
null
作为第一个参数调用它。你认为这会有什么影响?当它是
getTiger()
代码的一部分时,我看不出它是如何“与此无关”的。同样,我仍然不知道您希望从哪里获得信息。即使
ResolveNotTranslation
返回了一些内容,
EntityResolution.getTigerFromName
在您的测试环境中做什么?你在测试中调试过代码了吗?你说得对。谢谢,很抱歉,我没有说这些。这是一个生产代码,与您描述的maven结构相同。但是当我执行
assertNotNull(tigerFinderPage.getTiger())时它失败了。我已经对这个方法进行了调试
tigerFinderPage.getTiger()
它返回一个tigerManagerProxy对象。