如何在 JUnit 中测试局部变量以增强代码覆盖率

How to test a local variable in JUnit to enhance code coverage

我正在使用 JUnit API 测试方法,我想测试局部变量的值,以便获得更好的分支覆盖率。在被测方法中 widgets 是一个 List 类型的变量,在调试时我发现它不为空。我想测试 Null 但我不确定如何更改它的值?

正在测试的方法:

public boolean preProcess(ServiceContext ctx) throws ProcessorException {
    logMethodStartDebug( ctx, CLASS_NAME, "preProcess(ServiceContext, Object)" );

    try {

        if( Constants.YES.equalsIgnoreCase( EISSpringUtil.getMessage( ENABLE_SELF_HEALING_FLAG ) ) ) {          
            if( AppContext.getApplicationContext().containsBean( ISO + AGGREGATOR_HEALTH_PREFIX ) ) {
                IMonitoringWidgetAggregator aggregator = (IMonitoringWidgetAggregator)AppContext.getBean( ISO + AGGREGATOR_HEALTH_PREFIX );
                List<MonitoringWidget> widgets = aggregator.aggregate();

                if( widgets != null && widgets.size() > 0 ) {               
                    for( MonitoringWidget mw : widgets ) {
                        if( mw.getStatus().equals( MonitoringStatus.FAIL ) ) {
                            ctx.addMessage( ErrorMessageUtil.generateMessage( getMessageFactory(), ErrorCodeConstants.STATUS_6000, new Object[] { ctx.getSystemName(), mw.getMonitoringCode()} ) ); 
                            return false;
                        }
                    }
                }
            }
        }

        return true;
    } finally {
        logMethodEndDebug( ctx, CLASS_NAME, "preProcess(ServiceContext, Object)" );
    }
}

正面场景的 JUnit 测试用例

@Test
public void testPreProcess() throws Exception {
    AppContext.setApplicationContext( applicationContext );
    ServiceContext ctx = new ServiceContext();

    boolean b = preProcess( ctx );
    assertFalse( b );
    assertNotNull( ctx );
    assertNotNull( ctx.getMessages() );
    assertNotNull( ctx.getMessages().get( 0 ) );
    assertEquals( "code:6000", ctx.getMessages().get( 0 ) .getMessageCode() );
}

提前致谢

您需要在 AppContext 中为单元测试定义您的测试 bean:

IMonitoringWidgetAggregator aggregator = (IMonitoringWidgetAggregator)AppContext.getBean( ISO + AGGREGATOR_HEALTH_PREFIX );

您确实可以访问聚合器,这意味着例如,如果您使用 CDI/IoC 兼容的框架,例如 Spring(或者只是普通的旧 J2EE,甚至像 KumulzuEE 之类的东西),您可以使用@ContextConfiguration 和@Configuration 注释指定您希望从何处注入@Beans。因此,如果您想要测试整个集成,您可以选择注入模拟 IMonitoringWidgetAggregator 或实现的真实实例。

使小部件处理成为单元测试重点的一个直接选择是将该处理重构为一个单独的方法:

public boolean preProcess(ServiceContext ctx) throws ProcessorException {
    logMethodStartDebug( ctx, CLASS_NAME, "preProcess(ServiceContext, Object)" );

    try {
        if( Constants.YES.equalsIgnoreCase( EISSpringUtil.getMessage( ENABLE_SELF_HEALING_FLAG ) ) ) {          
            if( AppContext.getApplicationContext().containsBean( ISO + AGGREGATOR_HEALTH_PREFIX ) ) {
                IMonitoringWidgetAggregator aggregator = (IMonitoringWidgetAggregator)AppContext.getBean( ISO + AGGREGATOR_HEALTH_PREFIX );
                List<MonitoringWidget> widgets = aggregator.aggregate();
                return preProcessWidgets(widgets);
            }
        }

        return true;
    } finally {
        logMethodEndDebug( ctx, CLASS_NAME, "preProcess(ServiceContext, Object)" );
    }
}

private boolean preProcessWidgets(final List<MonitoringWidget> widgets) {
    if( widgets != null && widgets.size() > 0 ) {               
        for( MonitoringWidget mw : widgets ) {
            if( mw.getStatus().equals( MonitoringStatus.FAIL ) ) {
                ctx.addMessage( ErrorMessageUtil.generateMessage( getMessageFactory(), ErrorCodeConstants.STATUS_6000, new Object[] { ctx.getSystemName(), mw.getMonitoringCode()} ) ); 
                return false;
            }
        }
    }
    return true;
}

使用这种结构,您现在可以轻松编写新的 JUnit 测试用例,重点关注 preProcessWidgets 方法中执行的小部件处理,例如:传递 null List,传递一个空的 List,您还可以自由地以对您的应用程序有意义的任何其他方式模拟 widgets 参数。