首页 > 解决方案 > 模拟 databaseMetaData.getTables() 方法时 ResultSet 为空

问题描述

我正在尝试为一个检查数据库中是否存在表的类编写单元测试用例。我已经使用了DatabaseMetadata接口并Resultset实现了它。现在我正在尝试为此编写一个单元测试用例,但在模拟时

数据库元数据 getTables()

方法,我的结果集为空。谁能告诉我我做错了什么?还有没有更好的方法来检查数据库中的表?

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.core.JsonProcessingException;

@Component
public class DataBaseTableScanner {
    
    public DataBaseTableScanner() {
        super();
    }
    
    private DataSource datasource;
    
    @Autowired
    public DataBaseTableScanner(DataSource datasource) {
        this.datasource = datasource;
    }
    
    public void setDataSource(DataSource datasource) {
        this.datasource = datasource;
    }
    
    
    public boolean checkForTableInDataBase(String entityName) throws SQLException {     
        try(Connection con = datasource.getConnection()){
            DatabaseMetaData databaseMetaData = con.getMetaData();
            String tableName = entityName.toUpperCase();
            String[] types = {"TABLE"};
            resultSet = databaseMetaData.getTables(null, null, tableName, types);
            boolean tableExistFlag = resultSet.next();
            if(tableExistFlag) {
                System.out.println("Check Table:: "+ tableName + " :Table exits in Database!!");
            }else {
                System.out.println("Check Table:: "+ tableName + " :Table does not exits in Database!!");
            }
            return tableExistFlag;
            
        }
    }
}

我的单元测试用例


import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.sql.DataSource;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mapstruct.BeforeMapping;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class DataBaseTableScannerTest {
    
    @InjectMocks
    DataBaseTableScanner dataBaseTableScanner;
    
    @Mock
    DataSource datasource;
    
    @Mock
    Connection connection;
    
    @Mock
    DatabaseMetaData databaseMetaData;
    
    @Mock
    ResultSet resultSet;
    
    
    @Before
    public void setUp() throws TenantResolvingException, TenantNotFoundException, SQLException {
    
        dataBaseTableScanner.setDataSource(datasource);

        
        when(datasource.getConnection()).thenReturn(connection);
        when(connection.getMetaData()).thenReturn(databaseMetaData);
        String tableName = null;
        String[] types = null;
        //      String tableName = "task";
        //      String[] types = {"TABLE"};
         when(databaseMetaData.getTables(null, null, tableName, types)).thenReturn(resultSet);
        
    }
    
    
    @Test
    public void testIsTableExists() throws SQLException {
        boolean tbexists = dataBaseTableScanner.checkForTableInDataBase("task");
        assertTrue(tbexists);
    }

标签: javaunit-testingjdbcjunitmockito

解决方案


您使用参数模拟方法databaseMetaData.getTables(null, null, null, null)),因为在 setup 方法中:

String tableName = null;
String[] types = null;

但是当你调用checkForTableInDataBase方法时,它内部会调用getTables具有不同参数的方法:

String tableName = entityName.toUpperCase();
String[] types = {"TABLE"};

所以你应该重写你 when 方法:

 when(databaseMetaData.getTables(null, null, "task".toUpperCase(), {"TABLE"})).thenReturn(resultSet);

当然,它仅在您使用“任务”作为输入参数的情况下才有效dataBaseTableScanner.checkForTableInDataBase()


推荐阅读