首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何模拟新的SimpleJdbcCall

如何模拟新的SimpleJdbcCall
EN

Stack Overflow用户
提问于 2021-01-28 04:29:48
回答 1查看 236关注 0票数 0

你能帮我模拟一下SimpleJdbcCall吗?

要测试的实际类如下所示。

代码语言:javascript
复制
import java.sql.Types;
import java.util.HashMap;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;


@Component
public class HeartBeat {

    private static final Logger LOGGER = LogManager.getLogger(HeartBeat.class);

    @Autowired
    private DataSource dataSource;

    private JdbcTemplate jdbcTemplate;
    private SimpleJdbcCall jdbcCall;

    
    @PostConstruct
    private void applicationStarted() {
        LOGGER.info("Application has Started.");
        DBCall();
    }
    
    @Scheduled(fixedRateString="${application.heartbeatInterval}")
    public void sendHeartbeat() {
        DBCall();
    }
    
    private void DBCall() {

        if ( this.jdbcTemplate == null ) {
            this.jdbcTemplate = new JdbcTemplate(dataSource);
        }
        
        jdbcTemplate.setResultsMapCaseInsensitive(true);

        jdbcCall = new SimpleJdbcCall(jdbcTemplate)
            .withSchemaName("schema")
            .withCatalogName("catalogName")
            .withProcedureName("cleanup");

        jdbcCall.execute(new HashMap<String, Object>(0));
        
        jdbcCall = new SimpleJdbcCall(jdbcTemplate)
            .withSchemaName("schema")
            .withCatalogName("catalogName")
            .withProcedureName("register")
            .declareParameters(new SqlParameter("id", Types.VARCHAR))
            .declareParameters(new SqlParameter("name", Types.VARCHAR));
        MapSqlParameterSource paramMap = new MapSqlParameterSource().addValue("id", "abc").addValue("name", "def");
        
        jdbcCall.execute(paramMap);

    }
}

为了测试上面的代码,我创建了

代码语言:javascript
复制
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyMap;

import java.util.HashMap;
import java.util.Map;

public class HeartBeatTest {
    HeartBeat heartBeat;

    private JdbcTemplate mockedJdbcTemplate;
    private SimpleJdbcCall mockedJdbcCall;
    private Map<String, Object> result;
    
    @Before
    public void setUp() throws Exception {
        this.heartBeatComponent = new HeartBeatComponent();
        result = new HashMap<String, Object>();
        
        mockedJdbcTemplate = Mockito.mock(JdbcTemplate.class);
        mockedJdbcCall = Mockito.mock(SimpleJdbcCall.class);
    
        Whitebox.setInternalState(heartBeatComponent, "jdbcTemplate",mockedJdbcTemplate);
        Whitebox.setInternalState(heartBeatComponent, "jdbcCall",mockedJdbcCall);
        
        // section1
        //PowerMockito.whenNew(SimpleJdbcCall.class).withArguments(mockedJdbcTemplate).thenReturn(mockedJdbcCall);

        // section2
        PowerMockito.whenNew(SimpleJdbcCall.class).withAnyArguments().thenReturn(mockedJdbcCall);
        Mockito.when(mockedJdbcCall.withSchemaName(any(String.class))).thenReturn(mockedJdbcCall);
        Mockito.when(mockedJdbcCall.withCatalogName(any(String.class))).thenReturn(mockedJdbcCall);
        Mockito.when(mockedJdbcCall.withProcedureName(any(String.class))).thenReturn(mockedJdbcCall);

    }
    
    @Test
    public void sendHeartbeatTest() {
        Mockito.when(mockedJdbcCall.execute(anyMap())).thenReturn(result);
        Mockito.when(mockedJdbcCall.execute(any(MapSqlParameterSource.class))).thenReturn(result);
        
        heartBeat.sendHeartbeat();
        
        Mockito.verify(mockedJdbcCall, Mockito.times(1)).execute(anyMap());
        Mockito.verify(mockedJdbcCall, Mockito.times(1)).execute(any(MapSqlParameterSource.class));
        
    }
    
}

但它并没有像预期的那样工作。我在调试模式中看到的是,jdbcCall获得了mockedJdbcCall,但由于新的SimpleJdbcCall()以及.withSchemaName等,它被simpleJdbcCall覆盖了。我的预期是当调用新的SimpleJdbcCall返回mockedJdbcCall时,我设置了PowerMockito.whenNew...

我已经尝试了PowerMockito.whenNew的第1节和第2节,我是否误解了PowerMockito.whenNew?或者遗漏了代码中的任何东西?

请给我指引。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-01-28 04:52:12

您需要告诉PowerMock,您希望模拟HeartBeat类内部的SimpleJdbcCall类的构造。尝试向您的测试类添加以下注释:

代码语言:javascript
复制
@RunWith(PowerMockRunner.class)
@PrepareForTest(HeartBeat.class)
public class HeartBeatTest {
  ...
}

参考:how-to-mock-construction-of-new-objects

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65926898

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档