摘要 class 受保护的方法 junit 测试用例

abstract class protected method junit test case

考虑代码:

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 的最佳实践并将生产代码和测试它的代码放在同一个包中,以便允许访问protected 成员,但 在不同的源文件夹中 ,因此非生产代码不会干扰生产代码。例如,在 Maven 的结构中:

-- src
   +-- main
       +-- java
           +-- org
               +-- mypackage # Production code for org.mypackage
   +-- test
       +-- java
           +-- org
               +-- mypackage # Testing code for org.mypackage

如果这不是一个选项,您可以继承抽象 class 并增加所述方法的可见性,以便测试可以访问它:

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());
    }
}

测试非 public 成员将您的测试与您的实现联系起来,使重构变得更加困难。

如果它足够重要以至于无法通过 public 界面进行测试,那么它必须是单独的功能,可以存在于它自己的 class à la Single Responsibility Principle

在这种情况下,我会有一个单独的 class 和测试 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;
    }
}

然后在您的 class:

中使用它
abstract public class TigerFinderPage extends TigerPage
    private final LazyTigerFactory tigerFactory = new LazyTigerFactory();
    protected Manager getTiger(){
       return tigerFactory.getTiger();
    }

好处

  • 您可以从工厂测试中获得围绕创建的完整测试覆盖率,而不会弄乱您的 TigerFinderPage 测试。
  • 您以后可以随意轻松地更改 LazyTigerFactory
  • TigerFinderPage 具有较少的直接依赖关系。
  • TigerFinderPage 更小,更少 Lazy/Entity 样板使这个 class 真正做的事情变得混乱(它的单一职责)。
  • 您甚至可以更改为注入一个完全解耦的工厂接口,这可能有助于其他测试。