摘要 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 真正做的事情变得混乱(它的单一职责)。
- 您甚至可以更改为注入一个完全解耦的工厂接口,这可能有助于其他测试。
考虑代码:
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 真正做的事情变得混乱(它的单一职责)。- 您甚至可以更改为注入一个完全解耦的工厂接口,这可能有助于其他测试。