Skip to content

Commit

Permalink
Merge pull request #1826 from schemacrawler/mock
Browse files Browse the repository at this point in the history
Refactor mocking for connections, database metadata, statements and result sets
  • Loading branch information
sualeh authored Jan 7, 2025
2 parents 1637c32 + da52150 commit a1e3875
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,8 @@
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.matchesPattern;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import static schemacrawler.test.utility.DatabaseTestUtility.getCatalog;
import static schemacrawler.test.utility.DatabaseTestUtility.schemaRetrievalOptionsDefault;
import static schemacrawler.test.utility.ObjectPropertyTestUtility.checkBooleanProperties;
Expand Down Expand Up @@ -80,6 +78,7 @@
import schemacrawler.test.utility.ResolveTestContext;
import schemacrawler.test.utility.TestUtility;
import schemacrawler.test.utility.WithTestDatabase;
import us.fatehi.test.utility.TestObjectUtility;
import us.fatehi.utility.datasource.DatabaseConnectionSource;
import us.fatehi.utility.datasource.DatabaseConnectionSourceUtility;

Expand Down Expand Up @@ -236,20 +235,13 @@ public void primaryKey() throws Exception {
}

@Test
public void schemaCrawlerExceptions() throws Exception {
public void schemaCrawlerExceptions() {

final SchemaCrawlerOptions schemaCrawlerOptions =
SchemaCrawlerOptionsBuilder.newSchemaCrawlerOptions();

final Connection connection = mock(Connection.class);
final DatabaseMetaData databaseMetaData = mock(DatabaseMetaData.class);
when(connection.isClosed()).thenReturn(false);
when(connection.getMetaData()).thenReturn(databaseMetaData);
when(databaseMetaData.getDatabaseProductName()).thenReturn("databaseProductName");
when(databaseMetaData.getDatabaseProductVersion()).thenReturn("databaseProductVersion");
when(databaseMetaData.getURL()).thenReturn("connectionUrl");
when(databaseMetaData.getDriverName()).thenReturn("driverName");
when(databaseMetaData.getDriverVersion()).thenReturn("driverVersion");
final Connection connection = TestObjectUtility.mockConnection();
final DatabaseMetaData databaseMetaData = TestObjectUtility.mockDatabaseMetaData();

final DatabaseConnectionSource dataSource =
DatabaseConnectionSourceUtility.newTestDatabaseConnectionSource(connection);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
Expand All @@ -58,6 +58,7 @@
import schemacrawler.test.utility.TestContext;
import schemacrawler.test.utility.TestWriter;
import schemacrawler.test.utility.WithTestDatabase;
import us.fatehi.test.utility.TestObjectUtility;

@WithTestDatabase
@ResolveTestContext
Expand All @@ -74,13 +75,9 @@ public void getQueryFromResource() throws Exception {
@Test
public void executeAgainstColumnDataType() throws Exception {

final Connection mockConnection = mock(Connection.class);
final Statement mockStatement = mock(java.sql.Statement.class);
when(mockConnection.createStatement()).thenReturn(mockStatement);
when(mockStatement.execute(anyString())).thenReturn(true);
when(mockStatement.getResultSet()).thenReturn(mock(ResultSet.class));
when(mockStatement.getUpdateCount()).thenReturn(0);
when(mockStatement.execute(anyString())).thenReturn(true);
final Connection mockConnection = TestObjectUtility.mockConnection();
final Statement mockStatement = TestObjectUtility.mockStatement();
lenient().when(mockConnection.createStatement()).thenReturn(mockStatement);
final ColumnDataType mockColumnDataType = mock(ColumnDataType.class);
when(mockColumnDataType.getName()).thenReturn("mock-column-data-type-name");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@
import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
import static java.nio.file.StandardOpenOption.WRITE;
import static org.junit.jupiter.api.condition.JRE.JAVA_8;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static schemacrawler.schemacrawler.MetadataRetrievalStrategy.data_dictionary_all;
import static schemacrawler.schemacrawler.SchemaInfoMetadataRetrievalStrategy.tableColumnPrivilegesRetrievalStrategy;
import static schemacrawler.test.utility.DatabaseTestUtility.loadHsqldbConfig;
Expand All @@ -50,9 +48,6 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -91,37 +86,6 @@ public static Path copyResourceToTempFile(final String resource) throws IOExcept
return tempFile;
}

public static ResultSet createMockResultSet(final String[] columnNames, final Object[][] data)
throws SQLException {
final ResultSet rs = mock(ResultSet.class);
final ResultSetMetaData rsmd = mock(ResultSetMetaData.class);

// Mock ResultSetMetaData
when(rs.getMetaData()).thenReturn(rsmd);
when(rsmd.getColumnCount()).thenReturn(columnNames.length);
for (int i = 0; i < columnNames.length; i++) {
when(rsmd.getColumnName(i + 1)).thenReturn(columnNames[i]);
}

// Mock ResultSet data
final int[] rowIndex = {-1};
when(rs.next())
.thenAnswer(
invocation -> {
rowIndex[0]++;
return rowIndex[0] < data.length;
});

for (int i = 0; i < columnNames.length; i++) {
final int columnIndex = i;
when(rs.getObject(columnIndex + 1)).thenAnswer(invocation -> data[rowIndex[0]][columnIndex]);
when(rs.getString(columnIndex + 1))
.thenAnswer(invocation -> (String) data[rowIndex[0]][columnIndex]);
}

return rs;
}

public static void deleteIfPossible(final Path testOutputTargetFilePath) {
try {
deleteIfExists(testOutputTargetFilePath);
Expand Down
9 changes: 8 additions & 1 deletion schemacrawler-postgresql/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<project
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>us.fatehi</groupId>
Expand All @@ -21,6 +21,13 @@
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>us.fatehi</groupId>
<artifactId>schemacrawler-utility</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>us.fatehi</groupId>
<artifactId>schemacrawler-testdb</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import schemacrawler.schema.ColumnDataType;
import schemacrawler.server.postgresql.PostgreSQLEnumDataTypeHelper;
import schemacrawler.test.utility.DisableLogging;
import schemacrawler.test.utility.TestUtility;
import us.fatehi.test.utility.TestObjectUtility;

@DisableLogging
public class PostgreSQLEnumDataTypeHelperTest {
Expand All @@ -28,11 +28,7 @@ public class PostgreSQLEnumDataTypeHelperTest {
public void testGetEnumDataTypeInfo() throws Exception {
final Column column = mock(Column.class);
final ColumnDataType columnDataType = mockColumnDataType("enum_type", true);
final Connection connection = mock(Connection.class);

when(connection.createStatement()).thenReturn(mock(java.sql.Statement.class));
when(connection.createStatement().executeQuery(anyString()))
.thenReturn(mock(java.sql.ResultSet.class));
final Connection connection = TestObjectUtility.mockConnection();

final PostgreSQLEnumDataTypeHelper helper = new PostgreSQLEnumDataTypeHelper();
final EnumDataTypeInfo enumDataTypeInfo =
Expand All @@ -50,9 +46,9 @@ public void testGetEnumValues() throws Exception {
final Column column = mock(Column.class);
final ColumnDataType columnDataType = mockColumnDataType("enum_type", true);
final Connection connection = mock(Connection.class);
final Statement mockStatement = mock(java.sql.Statement.class);
final Statement mockStatement = mock(Statement.class);
final ResultSet mockResultSet =
TestUtility.createMockResultSet(
TestObjectUtility.mockResultSet(
new String[] {"TYPE_CATALOG", "TYPE_SCHEMA", "TYPE_NAME", "ENUM_LABEL"},
new Object[][] {
{null, "", columnDataType.getName(), "Moe"},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
package us.fatehi.test.utility;

import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import java.nio.file.AccessMode;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

import com.fasterxml.jackson.databind.ObjectMapper;

public class TestObjectUtility {
Expand Down Expand Up @@ -48,6 +57,99 @@ public static Map<String, Object> makeTestObjectMap() {
return testObjectMap;
}

public static Connection mockConnection() {
try {
final DatabaseMetaData mockDbMetaData = mockDatabaseMetaData();

final Connection mockConnection = mock(Connection.class);
lenient().when(mockConnection.getMetaData()).thenReturn(mockDbMetaData);
lenient().when(mockConnection.isClosed()).thenReturn(false);

final Statement mockStatement = mockStatement();
lenient().when(mockConnection.createStatement()).thenReturn(mockStatement);

final ResultSet mockResultSet = mockResultSet(new String[] {"col1"}, null);
lenient().when(mockStatement.getResultSet()).thenReturn(mockResultSet);

return mockConnection;
} catch (SQLException e) {
return mock(Connection.class);
}
}

public static Statement mockStatement() {
try {
final Statement mockStatement = mock(Statement.class);
lenient().when(mockStatement.execute(anyString())).thenReturn(true);
lenient().when(mockStatement.getResultSet()).thenReturn(mock(ResultSet.class));
lenient().when(mockStatement.getUpdateCount()).thenReturn(0);
lenient().when(mockStatement.execute(anyString())).thenReturn(true);
return mockStatement;
} catch (SQLException e) {
return mock(Statement.class);
}
}

public static DatabaseMetaData mockDatabaseMetaData() {
try {
final DatabaseMetaData mockDbMetaData = mock(DatabaseMetaData.class);
lenient().when(mockDbMetaData.getDatabaseProductName()).thenReturn("Fake Database");
lenient().when(mockDbMetaData.getDatabaseProductVersion()).thenReturn("0.0.1");
lenient().when(mockDbMetaData.getURL()).thenReturn("jdbc:fake://fakeconnection");
lenient().when(mockDbMetaData.getDriverName()).thenReturn("Fake Driver");
lenient().when(mockDbMetaData.getDriverVersion()).thenReturn("0.0.1");
lenient().when(mockDbMetaData.supportsCatalogsInTableDefinitions()).thenReturn(false);
lenient().when(mockDbMetaData.supportsSchemasInTableDefinitions()).thenReturn(true);
return mockDbMetaData;
} catch (final SQLException e) {
return mock(DatabaseMetaData.class);
}
}

public static ResultSet mockResultSet(final String[] columnNames, final Object[][] data)
throws SQLException {
final ResultSet mockRs = mock(ResultSet.class);
final ResultSetMetaData rsmd = mock(ResultSetMetaData.class);

// Mock ResultSetMetaData
lenient().when(mockRs.getMetaData()).thenReturn(rsmd);
lenient().when(rsmd.getColumnCount()).thenReturn(columnNames.length);
for (int i = 0; i < columnNames.length; i++) {
lenient().when(rsmd.getColumnName(i + 1)).thenReturn(columnNames[i]);
}

// Mock ResultSet data
final int[] rowIndex = {-1};
if (data == null) {
lenient().when(mockRs.next()).thenAnswer(invocation -> false);
} else {
lenient()
.when(mockRs.next())
.thenAnswer(
invocation -> {
rowIndex[0]++;
return rowIndex[0] < data.length;
});
}

if (data == null) {
lenient().when(mockRs.getObject(anyInt())).thenAnswer(invocation -> null);
lenient().when(mockRs.getString(anyInt())).thenAnswer(invocation -> (String) null);
} else {
for (int i = 0; i < columnNames.length; i++) {
final int columnIndex = i;
lenient()
.when(mockRs.getObject(columnIndex + 1))
.thenAnswer(invocation -> data[rowIndex[0]][columnIndex]);
lenient()
.when(mockRs.getString(columnIndex + 1))
.thenAnswer(invocation -> (String) data[rowIndex[0]][columnIndex]);
}
}

return mockRs;
}

private TestObjectUtility() {
// Prevent instantiation
}
Expand Down
Loading

0 comments on commit a1e3875

Please # to comment.