Fix possible Mockito concurrency issue
This commit is contained in:
parent
3df56ac794
commit
563880037e
|
@ -10,6 +10,7 @@ import org.hibernate.c3p0.internal.C3P0ConnectionProvider;
|
||||||
|
|
||||||
import org.hibernate.testing.util.ReflectionUtil;
|
import org.hibernate.testing.util.ReflectionUtil;
|
||||||
|
|
||||||
|
import org.mockito.Answers;
|
||||||
import org.mockito.MockSettings;
|
import org.mockito.MockSettings;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
|
@ -18,25 +19,24 @@ import org.mockito.Mockito;
|
||||||
*/
|
*/
|
||||||
public class C3P0ProxyConnectionProvider extends C3P0ConnectionProvider {
|
public class C3P0ProxyConnectionProvider extends C3P0ConnectionProvider {
|
||||||
|
|
||||||
private static final MockSettings VERIFIEABLE_MOCK_SETTINGS = Mockito.withSettings()
|
|
||||||
.defaultAnswer( org.mockito.Answers.CALLS_REAL_METHODS );
|
|
||||||
|
|
||||||
private final Map<Connection, Connection> connectionSpyMap = new HashMap<>();
|
private final Map<Connection, Connection> connectionSpyMap = new HashMap<>();
|
||||||
|
|
||||||
private static <T> T spy(T subject) {
|
|
||||||
return Mockito.mock( (Class<T>) subject.getClass(), VERIFIEABLE_MOCK_SETTINGS.spiedInstance( subject ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void configure(Map<String, Object> props) {
|
public void configure(Map<String, Object> props) {
|
||||||
super.configure( props );
|
super.configure( props );
|
||||||
DataSource ds = unwrap( DataSource.class );
|
DataSource ds = unwrap( DataSource.class );
|
||||||
DataSource dataSource = spy( ds );
|
DataSource dataSource = Mockito.mock(
|
||||||
|
DataSource.class,
|
||||||
|
Mockito.withSettings().defaultAnswer( Answers.CALLS_REAL_METHODS ).spiedInstance( ds )
|
||||||
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Mockito.doAnswer( invocation -> {
|
Mockito.doAnswer( invocation -> {
|
||||||
Connection connection = (Connection) invocation.callRealMethod();
|
Connection connection = (Connection) invocation.callRealMethod();
|
||||||
Connection connectionSpy = spy( connection );
|
Connection connectionSpy = Mockito.mock(
|
||||||
|
Connection.class,
|
||||||
|
Mockito.withSettings().defaultAnswer( Answers.CALLS_REAL_METHODS ).spiedInstance( connection )
|
||||||
|
);
|
||||||
connectionSpyMap.put( connectionSpy, connection );
|
connectionSpyMap.put( connectionSpy, connection );
|
||||||
return connectionSpy;
|
return connectionSpy;
|
||||||
} ).when( dataSource ).getConnection();
|
} ).when( dataSource ).getConnection();
|
||||||
|
|
|
@ -36,11 +36,6 @@ import org.mockito.internal.util.MockUtil;
|
||||||
*/
|
*/
|
||||||
public class PreparedStatementSpyConnectionProvider extends ConnectionProviderDelegate {
|
public class PreparedStatementSpyConnectionProvider 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 VERIFIABLE_MOCK_SETTINGS = Mockito.withSettings()
|
|
||||||
.defaultAnswer( org.mockito.Answers.CALLS_REAL_METHODS );
|
|
||||||
// We must keep around the mocked connections, otherwise they are garbage collected and trigger finalizers
|
// We must keep around the mocked connections, otherwise they are garbage collected and trigger finalizers
|
||||||
// Since we use CALLS_REAL_METHODS this might close underlying IO resources which makes other objects unusable
|
// Since we use CALLS_REAL_METHODS this might close underlying IO resources which makes other objects unusable
|
||||||
private static final Queue<Object> MOCKS = new LinkedBlockingQueue<>();
|
private static final Queue<Object> MOCKS = new LinkedBlockingQueue<>();
|
||||||
|
@ -76,8 +71,22 @@ public class PreparedStatementSpyConnectionProvider extends ConnectionProviderDe
|
||||||
|
|
||||||
public PreparedStatementSpyConnectionProvider(boolean allowMockVerificationOnStatements, boolean allowMockVerificationOnConnections, boolean forceSupportsAggressiveRelease) {
|
public PreparedStatementSpyConnectionProvider(boolean allowMockVerificationOnStatements, boolean allowMockVerificationOnConnections, boolean forceSupportsAggressiveRelease) {
|
||||||
super(forceSupportsAggressiveRelease);
|
super(forceSupportsAggressiveRelease);
|
||||||
this.settingsForStatements = allowMockVerificationOnStatements ? VERIFIABLE_MOCK_SETTINGS : MOCK_SETTINGS;
|
this.settingsForStatements = allowMockVerificationOnStatements ?
|
||||||
this.settingsForConnections = allowMockVerificationOnConnections ? VERIFIABLE_MOCK_SETTINGS : MOCK_SETTINGS;
|
getVerifiableMockSettings() :
|
||||||
|
getMockSettings();
|
||||||
|
this.settingsForConnections = allowMockVerificationOnConnections ?
|
||||||
|
getVerifiableMockSettings() :
|
||||||
|
getMockSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MockSettings getMockSettings() {
|
||||||
|
return 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 MockSettings getVerifiableMockSettings() {
|
||||||
|
return Mockito.withSettings().defaultAnswer( org.mockito.Answers.CALLS_REAL_METHODS );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Connection actualConnection() throws SQLException {
|
protected Connection actualConnection() throws SQLException {
|
||||||
|
|
Loading…
Reference in New Issue