不使用PowerMock,Mock无返回值方法中的JdbcTemplate实例创建
可行解决方案:重构代码解耦依赖创建逻辑
Mockito本身无法直接拦截new关键字创建对象的行为,核心思路是把JdbcTemplate的创建逻辑从setDataSource方法中抽离出来,让这部分逻辑可替换、可Mock。
方法1:抽离工厂方法(推荐)
修改BaseDao类,新增一个protected的工厂方法负责创建JdbcTemplate,测试时通过子类重写该方法返回Mock对象:
修改后的BaseDao代码
public class BaseDao { protected JdbcTemplate defaultTemplate; protected void setDataSource(DataSource dataSource) { this.defaultTemplate = createJdbcTemplate(dataSource); } // 抽离的工厂方法,供测试子类重写 protected JdbcTemplate createJdbcTemplate(DataSource dataSource) { return new JdbcTemplate(dataSource); } }
对应的测试代码
@ExtendWith(MockitoExtension.class) public class BaseDaoTest { @Mock private JdbcTemplate mockedDefaultTemplate; @Mock private DataSource mockDataSource; @Test public void testSetDataSource() { // 创建BaseDao的匿名子类,重写工厂方法返回Mock对象 BaseDao testDao = new BaseDao() { @Override protected JdbcTemplate createJdbcTemplate(DataSource dataSource) { // 验证传入的数据源是预设的Mock对象 assertSame(mockDataSource, dataSource); return mockedDefaultTemplate; } }; testDao.setDataSource(mockDataSource); // 验证defaultTemplate确实是我们的Mock对象 assertSame(mockedDefaultTemplate, testDao.defaultTemplate); } }
方法2:依赖注入JdbcTemplate(更符合DI原则)
如果允许调整原有设计,直接将JdbcTemplate作为依赖注入到BaseDao中,而非在setDataSource内创建,测试时直接注入Mock对象即可:
修改后的BaseDao代码
public class BaseDao { protected JdbcTemplate defaultTemplate; // 提供Setter注入入口 public void setDefaultTemplate(JdbcTemplate defaultTemplate) { this.defaultTemplate = defaultTemplate; } // 保留setDataSource方法,改为更新模板的数据源 protected void setDataSource(DataSource dataSource) { this.defaultTemplate.setDataSource(dataSource); } }
对应的测试代码
@ExtendWith(MockitoExtension.class) public class BaseDaoTest { @Mock private JdbcTemplate mockedDefaultTemplate; @Mock private DataSource mockDataSource; @Test public void testSetDataSource() { BaseDao testDao = new BaseDao(); testDao.setDefaultTemplate(mockedDefaultTemplate); testDao.setDataSource(mockDataSource); // 验证JdbcTemplate的setDataSource方法被正确调用 verify(mockedDefaultTemplate).setDataSource(mockDataSource); } }
补充说明
你提到的PowerMock虽能拦截new操作,但依赖字节码修改,与JUnit 5兼容性差,还会提升测试代码的耦合度,不利于长期维护。上面的重构方案更符合面向对象设计原则,同时让测试逻辑简洁可靠。
内容的提问来源于stack exchange,提问作者Plainsage
相关产品推荐
相关产品推荐

