HHH-12509 Reduce memory usage of PreparedStatementSpyConnectionProvider

This commit is contained in:
Sanne Grinovero 2018-04-19 14:17:19 +01:00
parent c7ea49a0b3
commit 782f023a5a
32 changed files with 68 additions and 44 deletions

View File

@ -47,7 +47,7 @@ public abstract class AbstractCriteriaLiteralHandlingModeTest extends BaseEntity
@Override @Override
public void buildEntityManagerFactory() { public void buildEntityManagerFactory() {
connectionProvider = new PreparedStatementSpyConnectionProvider(); connectionProvider = new PreparedStatementSpyConnectionProvider( false, false );
super.buildEntityManagerFactory(); super.buildEntityManagerFactory();
} }

View File

@ -59,7 +59,7 @@ public class CriteriaLiteralsTest extends BaseEntityManagerFunctionalTestCase {
@Override @Override
public void buildEntityManagerFactory() { public void buildEntityManagerFactory() {
connectionProvider = new PreparedStatementSpyConnectionProvider(); connectionProvider = new PreparedStatementSpyConnectionProvider( false, false );
super.buildEntityManagerFactory(); super.buildEntityManagerFactory();
} }

View File

@ -26,7 +26,7 @@ import static org.junit.Assert.assertTrue;
*/ */
public class DisableDiscardPersistenceContextOnCloseTest extends BaseEntityManagerFunctionalTestCase { public class DisableDiscardPersistenceContextOnCloseTest extends BaseEntityManagerFunctionalTestCase {
private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider(); private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider( false, false );
@Override @Override
protected Map getConfig() { protected Map getConfig() {

View File

@ -25,7 +25,7 @@ import static org.junit.Assert.fail;
*/ */
public class EnableDiscardPersistenceContextOnCloseTest extends BaseEntityManagerFunctionalTestCase { public class EnableDiscardPersistenceContextOnCloseTest extends BaseEntityManagerFunctionalTestCase {
private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider(); private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider( false, false );
@Override @Override
protected Map getConfig() { protected Map getConfig() {

View File

@ -50,7 +50,7 @@ public class EntityGraphWithFetchAnnotationTest
@Override @Override
public void buildEntityManagerFactory() { public void buildEntityManagerFactory() {
connectionProvider = new PreparedStatementSpyConnectionProvider(); connectionProvider = new PreparedStatementSpyConnectionProvider( false, false );
super.buildEntityManagerFactory(); super.buildEntityManagerFactory();
} }

View File

@ -32,7 +32,7 @@ import static org.junit.Assert.fail;
*/ */
public class StatementIsClosedAfterALockExceptionTest extends BaseEntityManagerFunctionalTestCase { public class StatementIsClosedAfterALockExceptionTest extends BaseEntityManagerFunctionalTestCase {
private static final PreparedStatementSpyConnectionProvider CONNECTION_PROVIDER = new PreparedStatementSpyConnectionProvider(); private static final PreparedStatementSpyConnectionProvider CONNECTION_PROVIDER = new PreparedStatementSpyConnectionProvider( false, false );
private Integer lockId; private Integer lockId;

View File

@ -59,7 +59,7 @@ public class NamedQueryCommentTest extends BaseEntityManagerFunctionalTestCase {
@Override @Override
public void buildEntityManagerFactory() { public void buildEntityManagerFactory() {
connectionProvider = new PreparedStatementSpyConnectionProvider(); connectionProvider = new PreparedStatementSpyConnectionProvider( false, false );
super.buildEntityManagerFactory(); super.buildEntityManagerFactory();
} }

View File

@ -26,7 +26,7 @@ import static org.junit.Assert.fail;
public class EmbeddableWithOneToMany_HHH_11302_xml_Test extends public class EmbeddableWithOneToMany_HHH_11302_xml_Test extends
BaseEntityManagerFunctionalTestCase { BaseEntityManagerFunctionalTestCase {
PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider(); PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider( false, false );
@Override @Override
public String[] getEjb3DD() { public String[] getEjb3DD() {

View File

@ -91,7 +91,7 @@ public class MySQLDropConstraintThrowsExceptionTest extends BaseUnitTestCase {
@Test @Test
public void testEnumTypeInterpretation() { public void testEnumTypeInterpretation() {
final PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider(); final PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider( false, false );
final StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder() final StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
.enableAutoClose() .enableAutoClose()

View File

@ -71,7 +71,7 @@ import static org.mockito.Mockito.verify;
@RequiresDialectFeature(DialectChecks.SupportsSequences.class) @RequiresDialectFeature(DialectChecks.SupportsSequences.class)
public class CriteriaQueryTest extends BaseNonConfigCoreFunctionalTestCase { public class CriteriaQueryTest extends BaseNonConfigCoreFunctionalTestCase {
private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider(); private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider( true, false );
@Override @Override
public String[] getMappings() { public String[] getMappings() {

View File

@ -41,7 +41,7 @@ public class ElementCollectionTest extends BaseNonConfigCoreFunctionalTestCase {
return new Class[] {Task.class}; return new Class[] {Task.class};
} }
private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider(); private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider( false, false );
@Override @Override
protected void addSettings(Map settings) { protected void addSettings(Map settings) {

View File

@ -39,7 +39,7 @@ import static org.mockito.Mockito.verify;
public class InsertOrderingWithBidirectionalManyToMany public class InsertOrderingWithBidirectionalManyToMany
extends BaseNonConfigCoreFunctionalTestCase { extends BaseNonConfigCoreFunctionalTestCase {
private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider(); private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider( true, false );
@Override @Override
protected Class[] getAnnotatedClasses() { protected Class[] getAnnotatedClasses() {

View File

@ -37,7 +37,7 @@ import static org.mockito.Mockito.verify;
public class InsertOrderingWithBidirectionalMapsIdOneToOne public class InsertOrderingWithBidirectionalMapsIdOneToOne
extends BaseNonConfigCoreFunctionalTestCase { extends BaseNonConfigCoreFunctionalTestCase {
private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider(); private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider( true, false );
@Override @Override
protected Class[] getAnnotatedClasses() { protected Class[] getAnnotatedClasses() {

View File

@ -39,7 +39,7 @@ import static org.mockito.Mockito.verify;
public class InsertOrderingWithBidirectionalOneToMany public class InsertOrderingWithBidirectionalOneToMany
extends BaseNonConfigCoreFunctionalTestCase { extends BaseNonConfigCoreFunctionalTestCase {
private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider(); private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider( true, false );
@Override @Override
protected Class[] getAnnotatedClasses() { protected Class[] getAnnotatedClasses() {

View File

@ -28,7 +28,7 @@ import static org.mockito.Mockito.verify;
public class InsertOrderingWithBidirectionalOneToOne public class InsertOrderingWithBidirectionalOneToOne
extends BaseNonConfigCoreFunctionalTestCase { extends BaseNonConfigCoreFunctionalTestCase {
private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider(); private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider( true, false );
@Override @Override
protected Class[] getAnnotatedClasses() { protected Class[] getAnnotatedClasses() {

View File

@ -45,7 +45,7 @@ import static org.junit.Assert.assertEquals;
public class InsertOrderingWithJoinedTableInheritance public class InsertOrderingWithJoinedTableInheritance
extends BaseNonConfigCoreFunctionalTestCase { extends BaseNonConfigCoreFunctionalTestCase {
private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider(); private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider( false, false );
@Override @Override
protected Class[] getAnnotatedClasses() { protected Class[] getAnnotatedClasses() {

View File

@ -44,7 +44,7 @@ import static org.junit.Assert.assertEquals;
public class InsertOrderingWithJoinedTableMultiLevelInheritance public class InsertOrderingWithJoinedTableMultiLevelInheritance
extends BaseNonConfigCoreFunctionalTestCase { extends BaseNonConfigCoreFunctionalTestCase {
private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider(); private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider( false, false );
@Override @Override
protected Class[] getAnnotatedClasses() { protected Class[] getAnnotatedClasses() {

View File

@ -39,7 +39,7 @@ import static org.mockito.Mockito.verify;
public class InsertOrderingWithManyToOne public class InsertOrderingWithManyToOne
extends BaseNonConfigCoreFunctionalTestCase { extends BaseNonConfigCoreFunctionalTestCase {
private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider(); private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider( true, false );
@Override @Override
protected Class[] getAnnotatedClasses() { protected Class[] getAnnotatedClasses() {

View File

@ -40,7 +40,7 @@ import static org.mockito.Mockito.verify;
public class InsertOrderingWithMultipleManyToOne public class InsertOrderingWithMultipleManyToOne
extends BaseNonConfigCoreFunctionalTestCase { extends BaseNonConfigCoreFunctionalTestCase {
private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider(); private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider( false, false );
@Override @Override
protected Class[] getAnnotatedClasses() { protected Class[] getAnnotatedClasses() {

View File

@ -45,7 +45,7 @@ import static org.junit.Assert.assertEquals;
public class InsertOrderingWithSingleTableInheritance public class InsertOrderingWithSingleTableInheritance
extends BaseNonConfigCoreFunctionalTestCase { extends BaseNonConfigCoreFunctionalTestCase {
private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider(); private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider( false, false );
@Override @Override
protected Class[] getAnnotatedClasses() { protected Class[] getAnnotatedClasses() {

View File

@ -45,7 +45,7 @@ import static org.junit.Assert.assertEquals;
public class InsertOrderingWithTablePerClassInheritance public class InsertOrderingWithTablePerClassInheritance
extends BaseNonConfigCoreFunctionalTestCase { extends BaseNonConfigCoreFunctionalTestCase {
private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider(); private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider( false, false );
@Override @Override
protected Class[] getAnnotatedClasses() { protected Class[] getAnnotatedClasses() {

View File

@ -36,7 +36,7 @@ import static org.mockito.Mockito.verify;
public class InsertOrderingWithUnidirectionalOneToOne public class InsertOrderingWithUnidirectionalOneToOne
extends BaseNonConfigCoreFunctionalTestCase { extends BaseNonConfigCoreFunctionalTestCase {
private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider(); private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider( true, false );
@Override @Override
protected Class[] getAnnotatedClasses() { protected Class[] getAnnotatedClasses() {

View File

@ -30,7 +30,7 @@ import static org.mockito.Mockito.verify;
public class SessionJdbcBatchTest public class SessionJdbcBatchTest
extends BaseNonConfigCoreFunctionalTestCase { extends BaseNonConfigCoreFunctionalTestCase {
private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider(); private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider( true, false );
@Override @Override
protected Class<?>[] getAnnotatedClasses() { protected Class<?>[] getAnnotatedClasses() {

View File

@ -50,7 +50,7 @@ public class QueryHintTest extends BaseNonConfigCoreFunctionalTestCase {
@Override @Override
protected void buildResources() { protected void buildResources() {
connectionProvider = new PreparedStatementSpyConnectionProvider(); connectionProvider = new PreparedStatementSpyConnectionProvider( false, false );
super.buildResources(); super.buildResources();
} }

View File

@ -35,7 +35,7 @@ import static org.mockito.Mockito.verify;
*/ */
public class QueryTimeOutTest extends BaseNonConfigCoreFunctionalTestCase { public class QueryTimeOutTest extends BaseNonConfigCoreFunctionalTestCase {
private static final PreparedStatementSpyConnectionProvider CONNECTION_PROVIDER = new PreparedStatementSpyConnectionProvider(); private static final PreparedStatementSpyConnectionProvider CONNECTION_PROVIDER = new PreparedStatementSpyConnectionProvider( true, false );
private static final String QUERY = "update AnEntity set name='abc'"; private static final String QUERY = "update AnEntity set name='abc'";
@Override @Override

View File

@ -33,7 +33,7 @@ import static org.mockito.Mockito.verify;
public abstract class AbstractSkipAutoCommitTest extends BaseEntityManagerFunctionalTestCase { public abstract class AbstractSkipAutoCommitTest extends BaseEntityManagerFunctionalTestCase {
private PreparedStatementSpyConnectionProvider connectionProvider = private PreparedStatementSpyConnectionProvider connectionProvider =
new PreparedStatementSpyConnectionProvider() { new PreparedStatementSpyConnectionProvider( false, true ) {
@Override @Override
protected Connection actualConnection() throws SQLException { protected Connection actualConnection() throws SQLException {
Connection connection = super.actualConnection(); Connection connection = super.actualConnection();

View File

@ -45,7 +45,7 @@ import static org.mockito.Mockito.verify;
public class JdbcTimeCustomTimeZoneTest public class JdbcTimeCustomTimeZoneTest
extends BaseNonConfigCoreFunctionalTestCase { extends BaseNonConfigCoreFunctionalTestCase {
private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider(); private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider( true, false );
private static final TimeZone TIME_ZONE = TimeZone.getTimeZone( private static final TimeZone TIME_ZONE = TimeZone.getTimeZone(
"America/Los_Angeles" ); "America/Los_Angeles" );

View File

@ -34,7 +34,7 @@ import static org.mockito.Mockito.verify;
public class JdbcTimeDefaultTimeZoneTest public class JdbcTimeDefaultTimeZoneTest
extends BaseNonConfigCoreFunctionalTestCase { extends BaseNonConfigCoreFunctionalTestCase {
private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider(); private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider( true, false );
@Override @Override
protected Class<?>[] getAnnotatedClasses() { protected Class<?>[] getAnnotatedClasses() {

View File

@ -42,7 +42,7 @@ import static org.mockito.Mockito.verify;
public class JdbcTimestampCustomSessionLevelTimeZoneTest public class JdbcTimestampCustomSessionLevelTimeZoneTest
extends BaseNonConfigCoreFunctionalTestCase { extends BaseNonConfigCoreFunctionalTestCase {
private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider(); private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider( true, false );
private static final TimeZone TIME_ZONE = TimeZone.getTimeZone( private static final TimeZone TIME_ZONE = TimeZone.getTimeZone(
"America/Los_Angeles" ); "America/Los_Angeles" );

View File

@ -42,7 +42,7 @@ import static org.mockito.Mockito.verify;
public class JdbcTimestampCustomTimeZoneTest public class JdbcTimestampCustomTimeZoneTest
extends BaseNonConfigCoreFunctionalTestCase { extends BaseNonConfigCoreFunctionalTestCase {
private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider(); private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider( true, false );
private static final TimeZone TIME_ZONE = TimeZone.getTimeZone( private static final TimeZone TIME_ZONE = TimeZone.getTimeZone(
"America/Los_Angeles" ); "America/Los_Angeles" );

View File

@ -33,7 +33,7 @@ import static org.mockito.Mockito.verify;
public class JdbcTimestampDefaultTimeZoneTest public class JdbcTimestampDefaultTimeZoneTest
extends BaseNonConfigCoreFunctionalTestCase { extends BaseNonConfigCoreFunctionalTestCase {
private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider(); private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider( true, false );
@Override @Override
protected Class<?>[] getAnnotatedClasses() { protected Class<?>[] getAnnotatedClasses() {

View File

@ -21,6 +21,7 @@ import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.testing.jdbc.ConnectionProviderDelegate; import org.hibernate.testing.jdbc.ConnectionProviderDelegate;
import org.mockito.ArgumentMatchers; import org.mockito.ArgumentMatchers;
import org.mockito.MockSettings;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.mockito.internal.util.MockUtil; import org.mockito.internal.util.MockUtil;
@ -29,23 +30,42 @@ import org.mockito.internal.util.MockUtil;
* intercept the underlying {@link PreparedStatement} method calls. * intercept the underlying {@link PreparedStatement} method calls.
* *
* @author Vlad Mihalcea * @author Vlad Mihalcea
* @author Sannne Grinovero
*/ */
public class PreparedStatementSpyConnectionProvider public class PreparedStatementSpyConnectionProvider extends ConnectionProviderDelegate {
extends ConnectionProviderDelegate {
private static final MockSettings MOCK_SETTINGS = Mockito.withSettings()
.stubOnly() //important optimisation: uses far less memory, at tradeoff of mocked methods no longer being verifiable but we often don't need that.
.defaultAnswer( org.mockito.Answers.CALLS_REAL_METHODS );
private static final MockSettings VERIFIEABLE_MOCK_SETTINGS = Mockito.withSettings()
.defaultAnswer( org.mockito.Answers.CALLS_REAL_METHODS );
private final Map<PreparedStatement, String> preparedStatementMap = new LinkedHashMap<>(); private final Map<PreparedStatement, String> preparedStatementMap = new LinkedHashMap<>();
private final List<String> executeStatements = new ArrayList<>(); private final List<String> executeStatements = new ArrayList<>( 4 );
private final List<String> executeUpdateStatements = new ArrayList<>(); private final List<String> executeUpdateStatements = new ArrayList<>( 4 );
private final List<Connection> acquiredConnections = new ArrayList<>( ); private final List<Connection> acquiredConnections = new ArrayList<>( 4 );
private final List<Connection> releasedConnections = new ArrayList<>( ); private final List<Connection> releasedConnections = new ArrayList<>( 4 );
private final MockSettings settingsForStatements;
private final MockSettings settingsForConnections;
/**
* @deprecated best use the {@link #PreparedStatementSpyConnectionProvider(boolean,boolean)} method to be explicit about the limitations.
*/
@Deprecated
public PreparedStatementSpyConnectionProvider() { public PreparedStatementSpyConnectionProvider() {
this( false, false );
} }
public PreparedStatementSpyConnectionProvider(ConnectionProvider connectionProvider) { /**
super( connectionProvider ); * Careful: the default is to use mocks which do not allow to verify invocations, as otherwise the
* memory usage of the testsuite is extremely high.
* When you really need to verify invocations, set the relevant constructor parameter to true.
*/
public PreparedStatementSpyConnectionProvider(boolean allowMockVerificationOnStatements, boolean allowMockVerificationOnConnections) {
this.settingsForStatements = allowMockVerificationOnStatements ? VERIFIEABLE_MOCK_SETTINGS : MOCK_SETTINGS;
this.settingsForConnections = allowMockVerificationOnConnections ? VERIFIEABLE_MOCK_SETTINGS : MOCK_SETTINGS;
} }
protected Connection actualConnection() throws SQLException { protected Connection actualConnection() throws SQLException {
@ -54,7 +74,7 @@ public class PreparedStatementSpyConnectionProvider
@Override @Override
public Connection getConnection() throws SQLException { public Connection getConnection() throws SQLException {
Connection connection = spy( actualConnection() ); Connection connection = instrumentConnection( actualConnection() );
acquiredConnections.add( connection ); acquiredConnections.add( connection );
return connection; return connection;
} }
@ -72,15 +92,15 @@ public class PreparedStatementSpyConnectionProvider
super.stop(); super.stop();
} }
private Connection spy(Connection connection) { private Connection instrumentConnection(Connection connection) {
if ( MockUtil.isMock( connection ) ) { if ( MockUtil.isMock( connection ) ) {
return connection; return connection;
} }
Connection connectionSpy = Mockito.spy( connection ); Connection connectionSpy = spy( connection, settingsForConnections );
try { try {
Mockito.doAnswer( invocation -> { Mockito.doAnswer( invocation -> {
PreparedStatement statement = (PreparedStatement) invocation.callRealMethod(); PreparedStatement statement = (PreparedStatement) invocation.callRealMethod();
PreparedStatement statementSpy = Mockito.spy( statement ); PreparedStatement statementSpy = spy( statement, settingsForStatements );
String sql = (String) invocation.getArguments()[0]; String sql = (String) invocation.getArguments()[0];
preparedStatementMap.put( statementSpy, sql ); preparedStatementMap.put( statementSpy, sql );
return statementSpy; return statementSpy;
@ -88,7 +108,7 @@ public class PreparedStatementSpyConnectionProvider
Mockito.doAnswer( invocation -> { Mockito.doAnswer( invocation -> {
Statement statement = (Statement) invocation.callRealMethod(); Statement statement = (Statement) invocation.callRealMethod();
Statement statementSpy = Mockito.spy( statement ); Statement statementSpy = spy( statement, settingsForStatements );
Mockito.doAnswer( statementInvocation -> { Mockito.doAnswer( statementInvocation -> {
String sql = (String) statementInvocation.getArguments()[0]; String sql = (String) statementInvocation.getArguments()[0];
executeStatements.add( sql ); executeStatements.add( sql );
@ -108,6 +128,10 @@ public class PreparedStatementSpyConnectionProvider
return connectionSpy; return connectionSpy;
} }
private static <T> T spy(T subject, MockSettings mockSettings) {
return Mockito.mock( (Class<T>) subject.getClass(), mockSettings.spiedInstance( subject ) );
}
/** /**
* Clears the recorded PreparedStatements and reset the associated Mocks. * Clears the recorded PreparedStatements and reset the associated Mocks.
*/ */