You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JUnit测试调用Controller方法时遇ClassNotLoadException求助

解决JUnit测试Controller时的ClassNotLoadException及断点无法进入问题

我来帮你分析下这个问题:你遇到的com.sun.jdi.ClassNotLoadException本质上是因为Mockito的使用方式不对——你现在用@Mock注解创建的是AvamarController的模拟代理对象,而不是Spring容器管理的真实Controller实例。这个Mock对象的方法默认是空实现(或者Mockito的默认占位行为),根本不会执行你写的Controller里的真实代码,所以调试断点无法触发,还会因为代理类的加载机制问题抛出异常。另外你传了null作为Model参数,这也是潜在的空指针风险。

下面给你两种针对性的解决方案:

方案一:测试真实Controller逻辑(推荐)

如果你想测试Controller的真实业务逻辑(比如验证model的属性是否正确、视图名称是否符合预期),应该用@InjectMocks创建真实的Controller实例,同时Mock它依赖的业务对象(比如avamarOSBO),避免调用真实的服务层代码。

修改后的测试类代码如下:

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.ui.Model;
import org.springframework.web.servlet.ModelAndView;
import com.emc.brsit.avamar.vo.AvamarAllComponentsVO;
import com.emc.brsit.common.util.CustomCompGuideException;

// 假设你的业务对象类型是AvamarOSBO,需要根据实际类名修改
import com.emc.brsit.avamar.service.AvamarOSBO;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath*:/Project/applicationContext servlet.xml")
public class AvamarControllerTest {
    private final static Logger LOGGER = LoggerFactory
            .getLogger(AvamarControllerTest.class);
    
    // 创建真实的Controller实例,并自动注入下面的Mock依赖
    @InjectMocks
    private AvamarController avamar;
    
    // Mock Controller依赖的业务对象,避免调用真实服务
    @Mock
    private AvamarOSBO avamarOSBO;
    
    @Mock
    private AvamarAllComponentsVO avamarComponent;
    
    @Mock
    private Model model; // 用Mock替代null,避免空指针

    @Before
    public void setupMock() {
        MockitoAnnotations.initMocks(this);
        
        // 提前Mock业务对象的方法返回值,让Controller逻辑能正常执行
        // 示例:根据实际方法返回值类型修改xxx
        Mockito.when(avamarOSBO.getApp_Hype_Feat_Filters("Features")).thenReturn(xxx);
        Mockito.when(avamarOSBO.getClientOSGroupedBY()).thenReturn(xxx);
        // 其他业务方法同理,按需Mock
    }

    @Test
    public void testGetCompGuidePage() {
        String productVersion ="7.5";
        ModelAndView modelView = null;
        try {
            modelView = avamar.getCompGuidePage(productVersion , avamarComponent, model );
            
            // 断言验证:判断返回的视图名称是否符合预期
            org.junit.Assert.assertEquals("AvamarCompGuideApp", modelView.getViewName());
            // 还可以验证model的属性是否被正确添加,比如:
            // Mockito.verify(model).addAttribute("link", productVersion);
        } catch (CustomCompGuideException e) {
            e.printStackTrace();
            org.junit.Assert.fail("测试失败,抛出异常:" + e.getMessage());
        }
    }
}

这个方案的核心逻辑:

  • @InjectMocks会初始化真实的AvamarController实例,并将所有@Mock标注的依赖(比如avamarOSBO)自动注入到Controller中。
  • 你可以通过Mockito.when()来指定业务对象方法的返回值,确保Controller的逻辑能完整执行,同时不会触发真实的数据库/服务调用。
  • 用@Mock模拟Model对象,避免传null导致空指针。

方案二:让Mock对象执行真实方法(仅适用于特定场景)

如果你的需求只是想让Mock的Controller对象执行真实的方法(比如测试上层调用逻辑),可以用thenCallRealMethod()告诉Mockito执行真实的方法实现。但注意:Controller的依赖(比如avamarOSBO)必须提前Mock,否则会出现空指针。

修改后的测试方法示例:

@Test
public void testGetCompGuidePage() {
    String productVersion ="7.5";
    Model model = Mockito.mock(Model.class);
    ModelAndView modelView = null;
    
    // 让Mock的Controller对象执行真实的getCompGuidePage方法
    Mockito.when(avamar.getCompGuidePage(productVersion, avamarComponent, model))
           .thenCallRealMethod();
    
    try {
        modelView = avamar.getCompGuidePage(productVersion , avamarComponent, model );
        // 这里可以添加断言逻辑
    } catch (CustomCompGuideException e) {
        e.printStackTrace();
    }
}

注意事项:

  • 这种方式依然需要MockController的所有依赖(比如avamarOSBO),否则会因为依赖为null抛出空指针异常。
  • 此方案更适合测试Controller方法的上层调用,而非验证Controller内部逻辑。

问题总结

  1. 你之前的测试用@Mock创建的是Controller的代理对象,不是真实实例,所以不会执行真实代码,断点无法触发,进而抛出类加载异常。
  2. 传null作为Model参数是潜在的空指针风险,必须用Mock对象替代。

内容的提问来源于stack exchange,提问作者Gaurav

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:21:31