Repository: neo4j-contrib/neo4j-jdbc
Pull request #280 (2021-09-06 22:14:34)

Remove PowerMock
Migrate tests with minimal production code changes.

Fix (some) warnings in affected files.


Patch:
diff --git a/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/BoltDriver.java b/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/BoltDriver.java
index 7c53fb3e..fa4000b2 100644
--- a/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/BoltDriver.java
+++ b/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/BoltDriver.java
@@ -56,13 +56,21 @@ public class BoltDriver extends BoltNeo4jDriverImpl {
 		}
 	}
 
+	private final DriverFactory driverFactory;
+
 	public BoltDriver() throws SQLException {
+		this(cache::getDriver);
+	}
+
+	// visible for testing
+	protected BoltDriver(DriverFactory driverFactory) {
 		super(JDBC_BOLT_PREFIX);
+		this.driverFactory = driverFactory;
 	}
 
 	@Override
-	protected Driver getDriver(List<URI> routingUris, Config config, AuthToken authToken, Properties info) throws URISyntaxException {
-		return cache.getDriver(routingUris, config, authToken, info);
+	protected Driver getDriver(List<URI> routingUris, Config config, AuthToken authToken, Properties info) {
+		return driverFactory.createDriver(routingUris, config, authToken, info);
 	}
 
 	@Override
@@ -79,9 +87,4 @@ public class BoltDriver extends BoltNeo4jDriverImpl {
     protected List<URI> buildRoutingUris(String boltUrl, Properties properties) throws URISyntaxException {
         return Arrays.asList(new URI(boltUrl));
     }
-
-	// visible for testing
-	public static void clearCache() {
-		cache.clear();
-	}
 }
diff --git a/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/BoltNeo4jParameterMetaData.java b/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/BoltNeo4jParameterMetaData.java
index cc00f8bd..104846c4 100644
--- a/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/BoltNeo4jParameterMetaData.java
+++ b/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/BoltNeo4jParameterMetaData.java
@@ -27,12 +27,13 @@ import org.neo4j.jdbc.Neo4jParameterMetaData;
  */
 public class BoltNeo4jParameterMetaData extends Neo4jParameterMetaData {
 
-	private BoltNeo4jPreparedStatement preparedStatement;
+	private final BoltNeo4jPreparedStatement preparedStatement;
 
 	public BoltNeo4jParameterMetaData(BoltNeo4jPreparedStatement preparedStatement) {
 		this.preparedStatement = preparedStatement;
 	}
 
+	// visible for testing
 	public BoltNeo4jPreparedStatement getPreparedStatement() {
 		return preparedStatement;
 	}
diff --git a/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/BoltNeo4jPreparedStatement.java b/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/BoltNeo4jPreparedStatement.java
index c14972b1..26c0e780 100644
--- a/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/BoltNeo4jPreparedStatement.java
+++ b/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/BoltNeo4jPreparedStatement.java
@@ -36,6 +36,8 @@ import java.time.ZoneId;
 import java.time.ZonedDateTime;
 import java.time.temporal.Temporal;
 import java.util.Calendar;
+import java.util.Collections;
+import java.util.List;
 import java.util.Map;
 import java.util.function.Function;
 
@@ -43,14 +45,18 @@ import static java.util.Arrays.copyOf;
 import static org.neo4j.jdbc.utils.BoltNeo4jUtils.executeInTx;
 import static org.neo4j.jdbc.utils.BoltNeo4jUtils.hasResultSet;
 
-/**
- * @author AgileLARUS
- * @since 3.0.0
- */
 public class BoltNeo4jPreparedStatement extends Neo4jPreparedStatement implements Loggable {
 
+	private final ResultSetFactory resultSetFactory;
+
 	private BoltNeo4jPreparedStatement(BoltNeo4jConnectionImpl connection, String rawStatement, int... rsParams) {
+		this(connection, BoltNeo4jResultSet::newInstance, rawStatement, rsParams);
+	}
+
+	// visible for testing
+	BoltNeo4jPreparedStatement(BoltNeo4jConnectionImpl connection, ResultSetFactory resultSetFactory, String rawStatement, int... rsParams) {
 		super(connection, rawStatement);
+		this.resultSetFactory = resultSetFactory;
 		this.resultSetParams = rsParams;
 	}
 
@@ -63,7 +69,7 @@ public class BoltNeo4jPreparedStatement extends Neo4jPreparedStatement implement
 
 	@Override public ResultSet executeQuery() throws SQLException {
 		return executeInternal((result) -> {
-			this.currentResultSet = BoltNeo4jResultSet.newInstance(this.hasDebug(), this, result, this.resultSetParams);
+			this.currentResultSet = this.resultSetFactory.create(this.hasDebug(), this, result, this.resultSetParams);
 			this.currentUpdateCount = -1;
 			return currentResultSet;
 		});
@@ -82,7 +88,7 @@ public class BoltNeo4jPreparedStatement extends Neo4jPreparedStatement implement
 		return executeInternal((result) -> {
 			boolean hasResultSet = hasResultSet((BoltNeo4jConnection) this.connection, this.statement);
 			if (hasResultSet) {
-				this.currentResultSet = BoltNeo4jResultSet.newInstance(this.hasDebug(), this, result, this.resultSetParams);
+				this.currentResultSet = this.resultSetFactory.create(this.hasDebug(), this, result, this.resultSetParams);
 				this.currentUpdateCount = -1;
 			} else {
 				this.currentResultSet = null;
@@ -178,4 +184,14 @@ public class BoltNeo4jPreparedStatement extends Neo4jPreparedStatement implement
 		checkClosed();
 		insertParameter(parameterIndex, x.getArray());
 	}
+
+	// visible for testing
+	Map<String, Object> getParameters() {
+		return this.parameters;
+	}
+
+	// visible for testing
+	List<Map<String, Object>> getBatchParameters() {
+		return this.batchParameters;
+	}
 }
diff --git a/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/BoltNeo4jResultSet.java b/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/BoltNeo4jResultSet.java
index eb3864f9..2523895f 100644
--- a/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/BoltNeo4jResultSet.java
+++ b/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/BoltNeo4jResultSet.java
@@ -107,7 +107,8 @@ public class BoltNeo4jResultSet extends Neo4jResultSet {
 	 *                  The defaults are <code>TYPE_FORWARD_ONLY</code>,
 	 *                  <code>CONCUR_READ_ONLY</code>,
 	 */
-	private BoltNeo4jResultSet(Statement statement, Result iterator, int... params) {
+	// visible for testing
+	BoltNeo4jResultSet(Statement statement, Result iterator, int... params) {
 		super(statement, params);
 		List<Record> recordList = iterator != null ? iterator.list() : Collections.emptyList();
 		Optional<Record> first = recordList.stream().findFirst();
diff --git a/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/BoltNeo4jStatement.java b/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/BoltNeo4jStatement.java
index e4f9d99b..3130383e 100644
--- a/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/BoltNeo4jStatement.java
+++ b/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/BoltNeo4jStatement.java
@@ -32,6 +32,7 @@ import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
 import java.util.ArrayList;
+import java.util.List;
 import java.util.function.Function;
 
 import static java.util.Arrays.copyOf;
@@ -44,28 +45,32 @@ import static org.neo4j.jdbc.utils.BoltNeo4jUtils.hasResultSet;
  */
 public class BoltNeo4jStatement extends Neo4jStatement {
 
+	private final ResultSetFactory resultSetFactory;
+
 	/**
 	 * Default Constructor
 	 *
 	 * @param connection The connection used for sharing the transaction between statements
 	 * @param rsParams   The params (type, concurrency and holdability) used to create a new ResultSet
 	 */
-	private BoltNeo4jStatement(BoltNeo4jConnectionImpl connection, int... rsParams) {
+	// visible for testing
+	BoltNeo4jStatement(BoltNeo4jConnectionImpl connection, ResultSetFactory resultSetFactory, int... rsParams) {
 		super(connection);
+		this.resultSetFactory = resultSetFactory;
 		this.resultSetParams = rsParams;
 		this.batchStatements = new ArrayList<>();
 	}
 
 	public static Statement newInstance(boolean debug, BoltNeo4jConnectionImpl connection, int... rsParams) {
-		Statement statement = new BoltNeo4jStatement(connection, rsParams);
-		((Neo4jStatement) statement).setDebug(debug);
+		Neo4jStatement statement = new BoltNeo4jStatement(connection, BoltNeo4jResultSet::newInstance, rsParams);
+		statement.setDebug(debug);
 		return (Statement) Proxy.newProxyInstance(BoltNeo4jStatement.class.getClassLoader(), new Class[] { Statement.class },
 				new Neo4jInvocationHandler(statement, debug));
 	}
 
 	@Override public ResultSet executeQuery(String sql) throws SQLException {
 		return executeInternal(sql, (result) -> {
-			this.currentResultSet = BoltNeo4jResultSet.newInstance(this.hasDebug(), this, result, this.resultSetParams);
+			this.currentResultSet = this.resultSetFactory.create(this.hasDebug(), this, result, this.resultSetParams);
 			this.currentUpdateCount = -1;
 			return this.currentResultSet;
 		});
@@ -127,5 +132,8 @@ public class BoltNeo4jStatement extends Neo4jStatement {
 		return result;
 	}
 
-
+	// visible for testing
+	List<String> getBatchStatements() {
+		return batchStatements;
+	}
 }
diff --git a/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/DriverFactory.java b/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/DriverFactory.java
new file mode 100644
index 00000000..b8c381c6
--- /dev/null
+++ b/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/DriverFactory.java
@@ -0,0 +1,15 @@
+package org.neo4j.jdbc.bolt;
+
+import org.neo4j.driver.AuthToken;
+import org.neo4j.driver.Config;
+import org.neo4j.driver.Driver;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Properties;
+
+@FunctionalInterface
+public interface DriverFactory {
+
+    Driver createDriver(List<URI> routingUris, Config config, AuthToken authToken, Properties info);
+}
diff --git a/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/ResultSetFactory.java b/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/ResultSetFactory.java
new file mode 100644
index 00000000..c49753d3
--- /dev/null
+++ b/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/ResultSetFactory.java
@@ -0,0 +1,12 @@
+package org.neo4j.jdbc.bolt;
+
+import org.neo4j.driver.Result;
+
+import java.sql.ResultSet;
+import java.sql.Statement;
+
+@FunctionalInterface
+interface ResultSetFactory {
+
+    ResultSet create(boolean debug, Statement statement, Result iterator, int... params);
+}
diff --git a/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/cache/BoltDriverCache.java b/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/cache/BoltDriverCache.java
index 1558b467..3646cf7d 100644
--- a/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/cache/BoltDriverCache.java
+++ b/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/bolt/cache/BoltDriverCache.java
@@ -74,9 +74,4 @@ public class BoltDriverCache {
     public Map<BoltDriverCacheKey, Driver> getCache() {
         return Collections.unmodifiableMap(cache);
     }
-
-    // visible for testing
-    public void clear() {
-        cache.clear();
-    }
 }
diff --git a/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/boltrouting/BoltRoutingNeo4jDriver.java b/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/boltrouting/BoltRoutingNeo4jDriver.java
index cc371b6d..c3b6d435 100644
--- a/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/boltrouting/BoltRoutingNeo4jDriver.java
+++ b/neo4j-jdbc-bolt/src/main/java/org/neo4j/jdbc/boltrouting/BoltRoutingNeo4jDriver.java
@@ -23,6 +23,7 @@ import org.neo4j.driver.Config;
 import org.neo4j.driver.Driver;
 import org.neo4j.driver.GraphDatabase;
 import org.neo4j.driver.exceptions.ServiceUnavailableException;
+import org.neo4j.jdbc.bolt.DriverFactory;
 import org.neo4j.jdbc.bolt.cache.BoltDriverCache;
 import org.neo4j.jdbc.bolt.impl.BoltNeo4jDriverImpl;
 import org.neo4j.jdbc.utils.BoltNeo4jUtils;
@@ -32,7 +33,7 @@ import java.net.URISyntaxException;
 import java.sql.DriverManager;
 import java.sql.SQLException;
 import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 import java.util.Properties;
 
@@ -76,12 +77,20 @@ public class BoltRoutingNeo4jDriver extends BoltNeo4jDriverImpl {
         }
     }
 
+    private final DriverFactory driverFactory;
+
     public BoltRoutingNeo4jDriver() throws SQLException {
-        super(JDBC_BOLT_ROUTING_PREFIX);
+        this(cache::getDriver);
     }
 
-    public BoltRoutingNeo4jDriver(String prefix) throws SQLException {
+    public BoltRoutingNeo4jDriver(String prefix) {
         super(prefix);
+        this.driverFactory = cache::getDriver;
+    }
+
+    BoltRoutingNeo4jDriver(DriverFactory driverFactory) throws SQLException {
+        super(JDBC_BOLT_ROUTING_PREFIX);
+        this.driverFactory = driverFactory;
     }
 
     private boolean isSchemaMatchPrefix(String url) {
@@ -91,24 +100,20 @@ public class BoltRoutingNeo4jDriver extends BoltNeo4jDriverImpl {
 
     @Override
     protected Driver getDriver(List<URI> routingUris, Config config, AuthToken authToken, Properties info) throws URISyntaxException {
-        return cache.getDriver(routingUris, config, authToken, info);
+        return driverFactory.createDriver(routingUris, config, authToken, info);
     }
 
     @Override
     protected Properties getRoutingContext(String url, Properties properties) {
+        if (!isSchemaMatchPrefix(url) || !properties.containsKey(ROUTING_CONTEXT)) {
+            return new Properties();
+        }
         Properties props = new Properties();
-        if (isSchemaMatchPrefix(url) && properties.containsKey(ROUTING_CONTEXT)) {
-            List<String> routingParams;
-            if (properties.get(ROUTING_CONTEXT) instanceof String) {
-                routingParams = Arrays.asList(properties.getProperty(ROUTING_CONTEXT));
+        for (String routingParam : routingParameters(properties)) {
+            if (routingParam.startsWith(ALTERNATIVE_SERVERS)) {
+                props.put(ALTERNATIVE_SERVERS, routingParam.substring(ALTERNATIVE_SERVERS.length() + 1));
             } else {
-                routingParams = (List) properties.get(ROUTING_CONTEXT);
-            }
-            for (String routingParam : routingParams) {
-                if (routingParam.startsWith(ALTERNATIVE_SERVERS))
-                    props.put(ALTERNATIVE_SERVERS, routingParam.substring(ALTERNATIVE_SERVERS.length() + 1));
-                else
-                    props.put(ROUTING_CONTEXT, routingParam);
+                props.put(ROUTING_CONTEXT, routingParam);
             }
         }
         return props;
@@ -127,13 +132,13 @@ public class BoltRoutingNeo4jDriver extends BoltNeo4jDriverImpl {
     protected List<URI> buildRoutingUris(String boltUrl, Properties properties) throws URISyntaxException {
         URI firstServer = new URI(boltUrl);
         List<URI> routingUris = new ArrayList<>();
-        String[] servers = firstServer.getAuthority().split("\\,");
+        String[] servers = firstServer.getAuthority().split(",");
         for (String server : servers) {
             routingUris.add(new URI(firstServer.getScheme(), server, firstServer.getPath(), firstServer.getQuery(), firstServer.getFragment()));
         }
         if (properties.containsKey((ALTERNATIVE_SERVERS))) {
             String alternativeServers = properties.getProperty(ALTERNATIVE_SERVERS);
-            String[] alternativeServerList = alternativeServers.split("\\" + LIST_SEPARATOR);
+            String[] alternativeServerList = alternativeServers.split(LIST_SEPARATOR);
             for (String alternativeServer: alternativeServerList) {
                 routingUris.add(new URI(firstServer.getScheme(), alternativeServer, firstServer.getPath(), firstServer.getQuery(), firstServer.getFragment()));
             }
@@ -141,8 +146,11 @@ public class BoltRoutingNeo4jDriver extends BoltNeo4jDriverImpl {
         return routingUris;
     }
 
-    // visible for testing
-    public static void clearCache() {
-        cache.clear();
+    @SuppressWarnings("unchecked")
+    private List<String> routingParameters(Properties properties) {
+        if (properties.get(ROUTING_CONTEXT) instanceof String) {
+            return Collections.singletonList(properties.getProperty(ROUTING_CONTEXT));
+        }
+        return (List<String>) properties.get(ROUTING_CONTEXT);
     }
 }
diff --git a/neo4j-jdbc/src/main/java/org/neo4j/jdbc/Neo4jDriver.java b/neo4j-jdbc/src/main/java/org/neo4j/jdbc/Neo4jDriver.java
index 99d3b90f..3ea55a70 100644
--- a/neo4j-jdbc/src/main/java/org/neo4j/jdbc/Neo4jDriver.java
+++ b/neo4j-jdbc/src/main/java/org/neo4j/jdbc/Neo4jDriver.java
@@ -46,7 +46,7 @@ public abstract class Neo4jDriver implements java.sql.Driver {
 	/**
 	 * Driver prefix for the connection url.
 	 */
-	private String driverPrefix;
+	private final String driverPrefix;
 
 	/**
 	 * Constructor for extended class.
@@ -84,13 +84,9 @@ public abstract class Neo4jDriver implements java.sql.Driver {
 		String[] pieces = url.split(":");
 		if (pieces.length > 3 && url.startsWith(JDBC_PREFIX)) {
 			if (driverPrefix != null) {
-				if (pieces[2].matches(driverPrefix)) {
-					return true;
-				}
-			}
-			else {
-				return true;
+				return pieces[2].matches(driverPrefix);
 			}
+			return true;
 		}
 		return false;
 	}
diff --git a/neo4j-jdbc/src/main/java/org/neo4j/jdbc/Neo4jPreparedStatement.java b/neo4j-jdbc/src/main/java/org/neo4j/jdbc/Neo4jPreparedStatement.java
index 710fb24f..216f95b9 100644
--- a/neo4j-jdbc/src/main/java/org/neo4j/jdbc/Neo4jPreparedStatement.java
+++ b/neo4j-jdbc/src/main/java/org/neo4j/jdbc/Neo4jPreparedStatement.java
@@ -44,7 +44,7 @@ public abstract class Neo4jPreparedStatement extends Neo4jStatement implements P
 	protected String                    statement;
 	protected HashMap<String, Object>   parameters;
 	protected List<Map<String, Object>> batchParameters;
-	private   int                       parametersNumber;
+	protected int                       parametersNumber;
 	private static final List<Integer> UNSUPPORTED_TYPES = Collections .unmodifiableList(
 			Arrays.asList(
 					ARRAY,
diff --git a/neo4j-jdbc/src/main/java/org/neo4j/jdbc/Neo4jStatement.java b/neo4j-jdbc/src/main/java/org/neo4j/jdbc/Neo4jStatement.java
index 7472424d..8e59cd5e 100644
--- a/neo4j-jdbc/src/main/java/org/neo4j/jdbc/Neo4jStatement.java
+++ b/neo4j-jdbc/src/main/java/org/neo4j/jdbc/Neo4jStatement.java
@@ -104,7 +104,7 @@ public abstract class Neo4jStatement implements Statement, Loggable {
 	}
 
 	/**
-	 * Like javadoc said, this method should be called one times.
+	 * Like javadoc said, this method should be called one time.
 	 */
 	@Override public ResultSet getResultSet() throws SQLException {
 		this.checkClosed();
diff --git a/pom.xml b/pom.xml
index f131d6c1..73141757 100644
--- a/pom.xml
+++ b/pom.xml
@@ -78,7 +78,7 @@
 		<java.version>8</java.version>
 
 		<!-- Deps version -->
-		<powermock.version>2.0.9</powermock.version>
+		<mockito.version>3.12.4</mockito.version>
 		<junit.version>4.13.2</junit.version>
 		<jmh.version>1.19</jmh.version>
 		<neo4j.java.driver.version>4.3.1</neo4j.java.driver.version>
@@ -157,14 +157,9 @@
 				<version>${junit.version}</version>
 			</dependency>
 			<dependency>
-				<groupId>org.powermock</groupId>
-				<artifactId>powermock-module-junit4</artifactId>
-				<version>${powermock.version}</version>
-			</dependency>
-			<dependency>
-				<groupId>org.powermock</groupId>
-				<artifactId>powermock-api-mockito2</artifactId>
-				<version>${powermock.version}</version>
+				<groupId>org.mockito</groupId>
+				<artifactId>mockito-core</artifactId>
+				<version>${mockito.version}</version>
 			</dependency>
 
 			<!-- Deps for performance tests -->
@@ -203,13 +198,8 @@
 			<scope>test</scope>
 		</dependency>
 		<dependency>
-			<groupId>org.powermock</groupId>
-			<artifactId>powermock-api-mockito2</artifactId>
-			<scope>test</scope>
-		</dependency>
-		<dependency>
-			<groupId>org.powermock</groupId>
-			<artifactId>powermock-module-junit4</artifactId>
+			<groupId>org.mockito</groupId>
+			<artifactId>mockito-core</artifactId>
 			<scope>test</scope>
 		</dependency>
 	</dependencies>
@@ -413,34 +403,4 @@
 			</build>
 		</profile>
 	</profiles>
-
-	<!-- ================ -->
-	<!-- = Repositories = -->
-	<!-- ================ -->
-	<repositories>
-		<!-- Adding neo4j repository to have snapshot -->
-		<repository>
-			<id>neo4j-snapshot-repository</id>
-			<name>Neo4j Maven 2 snapshot repository</name>
-			<url>http://m2.neo4j.org/content/repositories/snapshots</url>
-			<snapshots>
-				<enabled>true</enabled>
-			</snapshots>
-			<releases>
-				<enabled>false</enabled>
-			</releases>
-		</repository>
-		<repository>
-			<id>neo4j-v4-repository</id>
-			<name>Neo4j Maven 2 snapshot repository</name>
-			<url>https://neo4j.bintray.com/community</url>
-			<snapshots>
-				<enabled>true</enabled>
-			</snapshots>
-			<releases>
-				<enabled>true</enabled>
-			</releases>
-		</repository>
-	</repositories>
-
 </project>


Test patch:
diff --git a/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/BoltNeo4jDriverTest.java b/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/BoltNeo4jDriverTest.java
index 70b94c06..07436afe 100644
--- a/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/BoltNeo4jDriverTest.java
+++ b/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/BoltNeo4jDriverTest.java
@@ -19,57 +19,40 @@
  */
 package org.neo4j.jdbc.bolt;
 
-import org.junit.After;
-import org.junit.Before;
 import org.junit.BeforeClass;
-import org.junit.FixMethodOrder;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.junit.runner.RunWith;
-import org.junit.runners.MethodSorters;
-import org.mockito.Mockito;
 import org.neo4j.driver.AuthTokens;
 import org.neo4j.driver.Config;
-import org.neo4j.driver.GraphDatabase;
-import org.neo4j.driver.internal.SecuritySettings;
 import org.neo4j.driver.internal.async.pool.PoolSettings;
-import org.neo4j.driver.internal.security.InternalAuthToken;
 import org.neo4j.jdbc.Neo4jDriver;
 import org.neo4j.jdbc.bolt.utils.JdbcConnectionTestUtils;
 import org.neo4j.jdbc.bolt.utils.Mocker;
-import org.powermock.api.mockito.PowerMockito;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
 
 import java.io.File;
-import java.net.URI;
 import java.net.URISyntaxException;
 import java.sql.Connection;
 import java.sql.Driver;
 import java.sql.SQLException;
 import java.util.Properties;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
 
-import static java.util.Collections.singletonMap;
 import static junit.framework.TestCase.assertFalse;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.internal.verification.VerificationModeFactory.atLeastOnce;
-import static org.neo4j.driver.Values.value;
-import static org.powermock.api.mockito.PowerMockito.verifyStatic;
+import static org.neo4j.driver.Config.TrustStrategy.Strategy.TRUST_SYSTEM_CA_SIGNED_CERTIFICATES;
+import static org.neo4j.jdbc.bolt.utils.JdbcConnectionTestUtils.PASSWORD;
+import static org.neo4j.jdbc.bolt.utils.JdbcConnectionTestUtils.USERNAME;
 
 /**
  * @author AgileLARUS
  * @since 3.0.0
  */
-@RunWith(PowerMockRunner.class)
-@PrepareForTest({GraphDatabase.class, Config.TrustStrategy.class, AuthTokens.class, SecuritySettings.class})
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+
 public class BoltNeo4jDriverTest {
 
 	@Rule public ExpectedException expectedEx = ExpectedException.none();
@@ -82,39 +65,28 @@ public class BoltNeo4jDriverTest {
 		mockedDriver = Mocker.mockDriver();
 	}
 
-	@After
-	public void prepare() {
-		BoltDriver.clearCache();
-	}
-
 	/*------------------------------*/
 	/*           connect            */
 	/*------------------------------*/
 	//WARNING!! NOT COMPLETE TEST!! Needs tests for parameters
 
-	@Test public void shouldConnectCreateConnection() throws SQLException, URISyntaxException {
-		PowerMockito.mockStatic(GraphDatabase.class);
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenReturn(mockedDriver);
-
-		Neo4jDriver driver = new BoltDriver();
+	@Test public void shouldConnectCreateConnection() throws SQLException {
+		Neo4jDriver driver = new BoltDriver((routingUris, config, authToken, info) -> mockedDriver);
 		Connection connection = driver.connect(COMPLETE_VALID_URL, null);
 		assertNotNull(connection);
 	}
 
 	@Test public void shouldConnectCreateConnectionWithNoAuthTokenWithPropertiesObjectWithoutUserAndPassword() throws SQLException, URISyntaxException {
-		PowerMockito.mockStatic(GraphDatabase.class);
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenReturn(mockedDriver);
-
 		Properties properties = new Properties();
 		properties.put("test", "TEST_VALUE");
 
-		Neo4jDriver driver = new BoltDriver();
+		Neo4jDriver driver = new BoltDriver((routingUris, config, authToken, info) -> mockedDriver);
 		Connection connection = driver.connect(COMPLETE_VALID_URL, properties);
 		assertNotNull(connection);
 	}
 
 	@Test public void shouldConnectReturnNullIfUrlNotValid() throws SQLException {
-		Neo4jDriver driver = new BoltDriver();
+		Neo4jDriver driver = new BoltDriver((routingUris, config, authToken, info) -> mockedDriver);
 		assertNull(driver.connect("jdbc:neo4j:http://localhost:7474", null));
 		assertNull(driver.connect("bolt://localhost:7474", null));
 		assertNull(driver.connect("jdbcbolt://localhost:7474", null));
@@ -123,63 +95,41 @@ public class BoltNeo4jDriverTest {
 
 	@Test public void shouldConnectThrowExceptionOnNullURL() throws SQLException {
 		expectedEx.expect(SQLException.class);
+		expectedEx.expectMessage("null is not a valid url");
 
-		Neo4jDriver driver = new BoltDriver();
+		Neo4jDriver driver = new BoltDriver((routingUris, config, authToken, info) -> mockedDriver);
 		driver.connect(null, null);
 	}
 
 	@Test public void shouldConnectThrowExceptionOnConnectionFailed() throws SQLException {
 		expectedEx.expect(SQLException.class);
+		expectedEx.expectMessage("Unable to connect to somehost:9999");
 
 		Neo4jDriver driver = new BoltDriver();
 		driver.connect("jdbc:neo4j:bolt://somehost:9999", null);
 	}
 
 	@Test public void shouldAcceptTrustStrategyParamsSystemCertificates() throws SQLException, URISyntaxException {
-		PowerMockito.mockStatic(GraphDatabase.class);
-		PowerMockito.mockStatic(Config.TrustStrategy.class);
-		PowerMockito.mockStatic(SecuritySettings.class);
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenReturn(mockedDriver);
-
 		Properties properties = new Properties();
 		properties.put("trust.strategy", "TRUST_SYSTEM_CA_SIGNED_CERTIFICATES");
+		AtomicBoolean called = new AtomicBoolean(false);
+		Driver driver = new BoltDriver((routingUris, config, authToken, info) -> {
+			assertEquals(TRUST_SYSTEM_CA_SIGNED_CERTIFICATES, config.trustStrategy().strategy());
+			assertTrue(called.compareAndSet(false, true));
+			return mockedDriver;
+		});
 
-		Driver driver = new BoltDriver();
 		driver.connect(COMPLETE_VALID_URL, properties);
 
-		verifyStatic(Config.TrustStrategy.class, atLeastOnce());
-		Config.TrustStrategy.trustSystemCertificates();
+		assertTrue(called.get());
 	}
 
-	@Test public void shouldAcceptTrustStrategyParamsCustomCertificateWithoutFile() throws SQLException {
+	@Test public void shouldNotAcceptTrustStrategyParamsCustomCertificateWithoutFile() throws SQLException {
 		expectedEx.expect(SQLException.class);
-		PowerMockito.mockStatic(Config.TrustStrategy.class);
+		expectedEx.expectMessage("Missing parameter 'trusted.certificate.file'");
 
 		Properties properties = new Properties();
 		properties.put("trust.strategy", "TRUST_CUSTOM_CA_SIGNED_CERTIFICATES");
-
-		Driver driver = new BoltDriver();
-		driver.connect(COMPLETE_VALID_URL, properties);
-	}
-
-	@Test public void shouldAcceptTrustStrategyParamsTrustFirstUseWithoutFile() throws SQLException {
-		expectedEx.expect(SQLException.class);
-		PowerMockito.mockStatic(Config.TrustStrategy.class);
-
-		Properties properties = new Properties();
-		properties.put("trust.strategy", "TRUST_ON_FIRST_USE");
-
-		Driver driver = new BoltDriver();
-		driver.connect(COMPLETE_VALID_URL, properties);
-	}
-
-	@Test public void shouldAcceptTrustStrategyParamsTrustSignedWithoutFile() throws SQLException {
-		expectedEx.expect(SQLException.class);
-		PowerMockito.mockStatic(Config.TrustStrategy.class);
-
-		Properties properties = new Properties();
-		properties.put("trust.strategy", "TRUST_SIGNED_CERTIFICATES");
-
 		Driver driver = new BoltDriver();
 		driver.connect(COMPLETE_VALID_URL, properties);
 	}
@@ -222,56 +172,41 @@ public class BoltNeo4jDriverTest {
 	/*------------------------------*/
 	/*          Config              */
 	/*------------------------------*/
-	@Test public void shouldNotRequireConfiguration() throws SQLException, URISyntaxException {
-		PowerMockito.mockStatic(GraphDatabase.class);
-
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
-			Config config = invocationOnMock.getArgument(2, Config.class);
-
+	@Test public void shouldNotRequireConfiguration() throws SQLException {
+		AtomicBoolean called = new AtomicBoolean(false);
+		Driver driver = new BoltDriver((routingUris, config, authToken, props) -> {
 			assertEquals(PoolSettings.DEFAULT_CONNECTION_ACQUISITION_TIMEOUT, config.connectionAcquisitionTimeoutMillis());
 			assertEquals(PoolSettings.DEFAULT_IDLE_TIME_BEFORE_CONNECTION_TEST, config.idleTimeBeforeConnectionTest());
 			assertEquals((int) TimeUnit.SECONDS.toMillis( 30 ), config.connectionTimeoutMillis());
 			assertFalse(config.encrypted());
 			assertFalse(config.logLeakedSessions());
-			// assertEquals(Config.LoadBalancingStrategy.LEAST_CONNECTED, config.loadBalancingStrategy());
 			assertEquals(PoolSettings.DEFAULT_MAX_CONNECTION_LIFETIME, config.maxConnectionLifetimeMillis());
 			assertEquals(PoolSettings.DEFAULT_MAX_CONNECTION_POOL_SIZE, config.maxConnectionPoolSize());
-
+			assertEquals(Config.TrustStrategy.trustSystemCertificates().strategy(), config.trustStrategy().strategy());
+			assertTrue(called.compareAndSet(false, true));
 			return mockedDriver;
 		});
 
-		Properties properties = new Properties();
-		Driver driver = new BoltDriver();
-		driver.connect(COMPLETE_VALID_URL, properties);
-	}
-
-	@Test public void shouldOverrideConfiguration_byUrl_empty_properties() throws SQLException, URISyntaxException {
-		PowerMockito.mockStatic(GraphDatabase.class);
+		driver.connect(COMPLETE_VALID_URL, new Properties());
 
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
-			Config config = invocationOnMock.getArgument(2, Config.class);
+		assertTrue(called.get());
+	}
 
+	@Test public void shouldOverrideConfiguration_byUrl_empty_properties() throws SQLException {
+		AtomicBoolean called = new AtomicBoolean(false);
+		Driver driver = new BoltDriver((routingUris, config, authToken, props) -> {
 			assertEquals(10, config.connectionAcquisitionTimeoutMillis());
 			assertEquals(600000, config.idleTimeBeforeConnectionTest());
 			assertEquals(123_000, config.connectionTimeoutMillis());
-			assertEquals(true, config.encrypted());
-			assertEquals(true, config.logLeakedSessions());
-			// assertEquals(Config.LoadBalancingStrategy.ROUND_ROBIN, config.loadBalancingStrategy());
+			assertTrue(config.encrypted());
+			assertTrue(config.logLeakedSessions());
 			assertEquals(123_000, config.maxConnectionLifetimeMillis());
 			assertEquals(3, config.maxConnectionPoolSize());
 			assertEquals(Config.TrustStrategy.trustSystemCertificates().strategy(), config.trustStrategy().strategy());
-
+			assertTrue(called.compareAndSet(false, true));
 			return mockedDriver;
 		});
 
-
-		PowerMockito.mockStatic(AuthTokens.class);
-
-		Mockito.when(AuthTokens.basic(Mockito.eq("neo4j"), Mockito.eq(null))).thenReturn(new InternalAuthToken( singletonMap( "scheme", value( "none" ) ) ));
-		Mockito.when(AuthTokens.none()).thenCallRealMethod();
-
-		Properties properties = new Properties();
-		Driver driver = new BoltDriver();
 		driver.connect(COMPLETE_VALID_URL+"?connection.acquisition.timeout=10" +
 				"&connection.liveness.check.timeout=10" +
 				"&connection.timeout=123000" +
@@ -281,34 +216,26 @@ public class BoltNeo4jDriverTest {
 				"&max.connection.lifetime=123000" +
 				"&max.connection.poolsize=3" +
 				"&trust.strategy=TRUST_SYSTEM_CA_SIGNED_CERTIFICATES" +
-				"&max.transaction.retry.time=1000", properties);
-	}
+				"&max.transaction.retry.time=1000", new Properties());
 
-	@Test public void shouldOverrideConfiguration_byUrl_no_properties() throws SQLException, URISyntaxException {
-		PowerMockito.mockStatic(GraphDatabase.class);
-
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
-			Config config = invocationOnMock.getArgument(2, Config.class);
+		assertTrue(called.get());
+	}
 
+	@Test public void shouldOverrideConfiguration_byUrl_no_properties() throws SQLException {
+		AtomicBoolean called = new AtomicBoolean(false);
+		Driver driver = new BoltDriver((routingUris, config, authToken, props) -> {
 			assertEquals(10, config.connectionAcquisitionTimeoutMillis());
 			assertEquals(600000, config.idleTimeBeforeConnectionTest());
 			assertEquals(123_000, config.connectionTimeoutMillis());
-			assertEquals(true, config.encrypted());
-			assertEquals(true, config.logLeakedSessions());
-//			// assertEquals(Config.LoadBalancingStrategy.ROUND_ROBIN, config.loadBalancingStrategy());
+			assertTrue(config.encrypted());
+			assertTrue(config.logLeakedSessions());
 			assertEquals(123_000, config.maxConnectionLifetimeMillis());
 			assertEquals(3, config.maxConnectionPoolSize());
 			assertEquals(Config.TrustStrategy.trustSystemCertificates().strategy(), config.trustStrategy().strategy());
-
+			assertTrue(called.compareAndSet(false, true));
 			return mockedDriver;
 		});
 
-		PowerMockito.mockStatic(AuthTokens.class);
-
-		Mockito.when(AuthTokens.basic(Mockito.eq("neo4j"), Mockito.eq(null))).thenReturn(new InternalAuthToken( singletonMap( "scheme", value( "none" ) ) ));
-		Mockito.when(AuthTokens.none()).thenCallRealMethod();
-
-		Driver driver = new BoltDriver();
 		driver.connect(COMPLETE_VALID_URL+"?connection.acquisition.timeout=10" +
 				"&connection.liveness.check.timeout=10" +
 				"&connection.timeout=123000" +
@@ -319,38 +246,30 @@ public class BoltNeo4jDriverTest {
 				"&max.connection.poolsize=3" +
 				"&trust.strategy=TRUST_SYSTEM_CA_SIGNED_CERTIFICATES" +
 				"&max.transaction.retry.time=1000", null);
-	}
 
-	@Test public void shouldOverrideConfiguration_byUrl_mix_properties() throws SQLException, URISyntaxException {
-		PowerMockito.mockStatic(GraphDatabase.class);
+		assertTrue(called.get());
+	}
 
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
-			Config config = invocationOnMock.getArgument(2, Config.class);
+	@Test public void shouldOverrideConfiguration_byUrl_mix_properties() throws SQLException {
+		AtomicBoolean called = new AtomicBoolean(false);
+		Properties prop = new Properties();
+		prop.setProperty("connection.acquisition.timeout","20");
+		prop.setProperty("connection.liveness.check.timeout","20");
+		prop.setProperty("connection.timeout","321000");
 
+		Driver driver = new BoltDriver((routingUris, config, authToken, info) -> {
 			assertEquals(10, config.connectionAcquisitionTimeoutMillis());
 			assertEquals(600000, config.idleTimeBeforeConnectionTest());
 			assertEquals(123_000, config.connectionTimeoutMillis());
-			assertEquals(true, config.encrypted());
-			assertEquals(true, config.logLeakedSessions());
-			// assertEquals(Config.LoadBalancingStrategy.ROUND_ROBIN, config.loadBalancingStrategy());
+			assertTrue(config.encrypted());
+			assertTrue(config.logLeakedSessions());
 			assertEquals(123_000, config.maxConnectionLifetimeMillis());
 			assertEquals(3, config.maxConnectionPoolSize());
 			assertEquals(Config.TrustStrategy.trustSystemCertificates().strategy(), config.trustStrategy().strategy());
-
+			assertTrue(called.compareAndSet(false, true));
 			return mockedDriver;
 		});
 
-		PowerMockito.mockStatic(AuthTokens.class);
-
-		Mockito.when(AuthTokens.basic(Mockito.eq("neo4j"), Mockito.eq(null))).thenReturn(new InternalAuthToken( singletonMap( "scheme", value( "none" ) ) ));
-		Mockito.when(AuthTokens.none()).thenCallRealMethod();
-
-		Properties prop = new Properties();
-		prop.setProperty("connection.acquisition.timeout","20");
-		prop.setProperty("connection.liveness.check.timeout","20");
-		prop.setProperty("connection.timeout","321000");
-
-		Driver driver = new BoltDriver();
 		driver.connect(COMPLETE_VALID_URL+"?connection.acquisition.timeout=10" +
 				"&connection.liveness.check.timeout=10" +
 				"&connection.timeout=123000" +
@@ -361,476 +280,290 @@ public class BoltNeo4jDriverTest {
 				"&max.connection.poolsize=3" +
 				"&trust.strategy=TRUST_SYSTEM_CA_SIGNED_CERTIFICATES" +
 				"&max.transaction.retry.time=1000", prop);
-	}
 
-	@Test public void shouldOverrideAuthentication_all_default() throws SQLException, URISyntaxException {
-		PowerMockito.mockStatic(GraphDatabase.class);
+		assertTrue(called.get());
+	}
 
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
+	@Test public void shouldOverrideAuthentication_all_default() throws SQLException {
+		AtomicBoolean called = new AtomicBoolean(false);
+		Driver driver = new BoltDriver((routingUris, config, authToken, props) -> {
+			assertEquals(AuthTokens.none(), authToken);
+			assertTrue(called.compareAndSet(false, true));
 			return mockedDriver;
 		});
 
-		PowerMockito.mockStatic(AuthTokens.class);
+		driver.connect(COMPLETE_VALID_URL+"?connection.acquisition.timeout=10", new Properties());
 
-		Mockito.when(AuthTokens.basic(Mockito.eq("neo4j"), Mockito.eq(null))).thenThrow(new IllegalArgumentException("Called basic auth instead of None"));
-		Mockito.when(AuthTokens.none()).thenCallRealMethod();
-
-		Properties prop = new Properties();
-
-		Driver driver = new BoltDriver();
-		driver.connect(COMPLETE_VALID_URL+"?connection.acquisition.timeout=10", prop);
+		assertTrue(called.get());
 	}
 
-	@Test public void shouldOverrideAuthentication_prop() throws SQLException, URISyntaxException {
-		PowerMockito.mockStatic(GraphDatabase.class);
-
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
+	@Test public void shouldOverrideAuthentication_prop() throws SQLException {
+		AtomicBoolean called = new AtomicBoolean(false);
+		Properties info = JdbcConnectionTestUtils.defaultInfo();
+		Driver driver = new BoltDriver((routingUris, config, authToken, props) -> {
+			assertEquals(AuthTokens.basic(USERNAME, PASSWORD), authToken);
+			assertTrue(called.compareAndSet(false, true));
 			return mockedDriver;
 		});
 
-		PowerMockito.mockStatic(AuthTokens.class);
-
-		Mockito.when(AuthTokens.basic(Mockito.eq("neo4j"), anyString())).thenThrow(new IllegalArgumentException("Wrong username"));
-		Mockito.when(AuthTokens.basic(Mockito.eq(JdbcConnectionTestUtils.USERNAME), Mockito.eq(JdbcConnectionTestUtils.PASSWORD))).thenReturn(new InternalAuthToken( singletonMap( "scheme", value( "none" ) ) ));
-		Mockito.when(AuthTokens.none()).thenThrow(new IllegalArgumentException("Called none auth instead of basic"));
+		driver.connect(COMPLETE_VALID_URL+"?connection.acquisition.timeout=10", info);
 
-		Properties prop = JdbcConnectionTestUtils.defaultInfo();
-
-		Driver driver = new BoltDriver();
-		driver.connect(COMPLETE_VALID_URL+"?connection.acquisition.timeout=10", prop);
+		assertTrue(called.get());
 	}
 
 	@Test public void shouldOverrideAuthentication_url() throws SQLException, URISyntaxException {
-		PowerMockito.mockStatic(GraphDatabase.class);
-
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
+		AtomicBoolean called = new AtomicBoolean(false);
+		Driver driver = new BoltDriver((routingUris, config, authToken, props) -> {
+			assertEquals(AuthTokens.basic(USERNAME, PASSWORD), authToken);
+			assertTrue(called.compareAndSet(false, true));
 			return mockedDriver;
 		});
 
-		PowerMockito.mockStatic(AuthTokens.class);
-
-		Mockito.when(AuthTokens.basic(Mockito.eq("neo4j"), anyString())).thenThrow(new IllegalArgumentException("Wrong username"));
-		Mockito.when(AuthTokens.basic(Mockito.eq(JdbcConnectionTestUtils.USERNAME), Mockito.eq(JdbcConnectionTestUtils.PASSWORD))).thenReturn(new InternalAuthToken( singletonMap( "scheme", value( "none" ) ) ));
-		Mockito.when(AuthTokens.none()).thenThrow(new IllegalArgumentException("Called none auth instead of basic"));
-
-		Properties prop = new Properties();
+		driver.connect(
+				String.format("%s?connection.acquisition.timeout=10&user=%s&password=%s", COMPLETE_VALID_URL, USERNAME, JdbcConnectionTestUtils.PASSWORD),
+				new Properties()
+		);
 
-		Driver driver = new BoltDriver();
-		driver.connect(COMPLETE_VALID_URL+"?connection.acquisition.timeout=10&user="+JdbcConnectionTestUtils.USERNAME+"&password="+JdbcConnectionTestUtils.PASSWORD, prop);
+		assertTrue(called.get());
 	}
 
 	@Test public void shouldOverrideAuthentication_prop_url() throws SQLException, URISyntaxException {
-		PowerMockito.mockStatic(GraphDatabase.class);
-
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
-			return mockedDriver;
-		});
-
-		PowerMockito.mockStatic(AuthTokens.class);
-
-		Mockito.when(AuthTokens.basic(Mockito.eq("neo4j"), anyString())).thenThrow(new IllegalArgumentException("Wrong username"));
-		Mockito.when(AuthTokens.basic(Mockito.eq(JdbcConnectionTestUtils.USERNAME), Mockito.eq(JdbcConnectionTestUtils.PASSWORD))).thenReturn(new InternalAuthToken( singletonMap( "scheme", value( "none" ) ) ));
-		Mockito.when(AuthTokens.none()).thenThrow(new IllegalArgumentException("Called none auth instead of basic"));
-
 		Properties prop = new Properties();
 		prop.setProperty("user","neo4j");
 		prop.setProperty("password","admin");
+		AtomicBoolean called = new AtomicBoolean(false);
+		Driver driver = new BoltDriver((routingUris, config, authToken, props) -> {
+			assertEquals(AuthTokens.basic(USERNAME, PASSWORD), authToken);
+			assertTrue(called.compareAndSet(false, true));
+			return mockedDriver;
+		});
 
-		Driver driver = new BoltDriver();
-		driver.connect(COMPLETE_VALID_URL+"?connection.acquisition.timeout=10&user="+JdbcConnectionTestUtils.USERNAME+"&password="+JdbcConnectionTestUtils.PASSWORD, prop);
-	}
-
-	@Test public void shouldConfigureConnectionAcquisitionTimeout() throws SQLException, URISyntaxException {
-		PowerMockito.mockStatic(GraphDatabase.class);
+		driver.connect(COMPLETE_VALID_URL+"?connection.acquisition.timeout=10&user="+ USERNAME+"&password="+JdbcConnectionTestUtils.PASSWORD, prop);
 
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
-			Config config = invocationOnMock.getArgument(2, Config.class);
+		assertTrue(called.get());
+	}
 
+	@Test public void shouldConfigureConnectionAcquisitionTimeout() throws SQLException {
+		Properties info = new Properties();
+		info.setProperty("connection.acquisition.timeout","10");
+		AtomicBoolean called = new AtomicBoolean(false);
+		Driver driver = new BoltDriver((routingUris, config, authToken, props) -> {
 			assertEquals(10, config.connectionAcquisitionTimeoutMillis());
-
+			assertTrue(called.compareAndSet(false, true));
 			return mockedDriver;
 		});
 
-		Properties info = new Properties();
-		info.setProperty("connection.acquisition.timeout","10");
-		Driver driver = new BoltDriver();
 		driver.connect(COMPLETE_VALID_URL, info);
+
+		assertTrue(called.get());
 	}
 
 	@Test
-	public void shouldRefuseConnectionAcquisitionTimeout() throws SQLException, URISyntaxException {
+	public void shouldRefuseConnectionAcquisitionTimeout() throws SQLException {
 		expectedEx.expect(SQLException.class);
 		expectedEx.expectMessage("connection.acquisition.timeout: XX is not a number");
-		PowerMockito.mockStatic(GraphDatabase.class);
-
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
-			Config config = invocationOnMock.getArgument(2, Config.class);
-			return mockedDriver;
-		});
-
 		Properties info = new Properties();
 		info.setProperty("connection.acquisition.timeout", "XX");
-		Driver driver = new BoltDriver();
+		Driver driver = new BoltDriver((routingUris, config, authToken, props) -> mockedDriver);
+
 		driver.connect(COMPLETE_VALID_URL, info);
 	}
 
 	@Test public void shouldConfigureIdleTimeBeforeConnectionTest() throws SQLException, URISyntaxException {
-		PowerMockito.mockStatic(GraphDatabase.class);
-
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
-			Config config = invocationOnMock.getArgument(2, Config.class);
-
+		AtomicBoolean called = new AtomicBoolean(false);
+		Properties info = new Properties();
+		info.setProperty("connection.liveness.check.timeout","10");
+		Driver driver = new BoltDriver((routingUris, config, authToken, props) -> {
 			assertEquals(600000, config.idleTimeBeforeConnectionTest());
-
+			assertTrue(called.compareAndSet(false, true));
 			return mockedDriver;
 		});
 
-		Properties info = new Properties();
-		info.setProperty("connection.liveness.check.timeout","10");
-		Driver driver = new BoltDriver();
 		driver.connect(COMPLETE_VALID_URL, info);
+		assertTrue(called.get());
 	}
 
 	@Test
 	public void shouldRefuseIdleTimeBeforeConnectionTest() throws SQLException, URISyntaxException {
 		expectedEx.expect(SQLException.class);
 		expectedEx.expectMessage("connection.liveness.check.timeout: XX is not a number");
-		PowerMockito.mockStatic(GraphDatabase.class);
-
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
-			Config config = invocationOnMock.getArgument(2, Config.class);
-			return mockedDriver;
-		});
 
 		Properties info = new Properties();
 		info.setProperty("connection.liveness.check.timeout","XX");
-		Driver driver = new BoltDriver();
+		Driver driver = new BoltDriver((routingUris, config, authToken, props) -> mockedDriver);
 		driver.connect(COMPLETE_VALID_URL, info);
 	}
 
 	@Test public void shouldConfigureConnectionTimeout() throws SQLException, URISyntaxException {
-		PowerMockito.mockStatic(GraphDatabase.class);
-
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
-			Config config = invocationOnMock.getArgument(2, Config.class);
-
+		Properties info = new Properties();
+		info.setProperty("connection.timeout","123000");
+		AtomicBoolean called = new AtomicBoolean(false);
+		Driver driver = new BoltDriver((routingUris, config, authToken, props) -> {
 			assertEquals(123_000, config.connectionTimeoutMillis());
-
+			assertTrue(called.compareAndSet(false, true));
 			return mockedDriver;
 		});
 
-		Properties info = new Properties();
-		info.setProperty("connection.timeout","123000");
-		Driver driver = new BoltDriver();
 		driver.connect(COMPLETE_VALID_URL, info);
+
+		assertTrue(called.get());
 	}
 
 	@Test
 	public void shouldRefuseConnectionTimeout() throws SQLException, URISyntaxException {
 		expectedEx.expect(SQLException.class);
 		expectedEx.expectMessage("connection.timeout: XX is not a number");
-		PowerMockito.mockStatic(GraphDatabase.class);
-
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
-			Config config = invocationOnMock.getArgument(2, Config.class);
-			return mockedDriver;
-		});
 
 		Properties info = new Properties();
 		info.setProperty("connection.timeout","XX");
-		Driver driver = new BoltDriver();
+		Driver driver = new BoltDriver((routingUris, config, authToken, props) -> mockedDriver);
 		driver.connect(COMPLETE_VALID_URL, info);
 	}
 
-	@Test public void shouldConfigureEncryption() throws SQLException, URISyntaxException {
-		PowerMockito.mockStatic(GraphDatabase.class);
-
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
-			Config config = invocationOnMock.getArgument(2, Config.class);
-
-			assertEquals(true, config.encrypted());
-
+	@Test public void shouldConfigureEncryption() throws SQLException {
+		Properties info = new Properties();
+		info.setProperty("encryption","true");
+		AtomicBoolean called = new AtomicBoolean(false);
+		Driver driver = new BoltDriver((routingUris, config, authToken, props) -> {
+			assertTrue(config.encrypted());
+			assertTrue(called.compareAndSet(false, true));
 			return mockedDriver;
 		});
 
-		Properties info = new Properties();
-		info.setProperty("encryption","true");
-		Driver driver = new BoltDriver();
 		driver.connect(COMPLETE_VALID_URL, info);
+
+		assertTrue(called.get());
 	}
 
 	@Test
-	public void shouldRefuseEncryption() throws SQLException, URISyntaxException {
+	public void shouldRefuseEncryption() throws SQLException {
 		expectedEx.expect(SQLException.class);
 		expectedEx.expectMessage("encryption: XX is not a boolean");
-		PowerMockito.mockStatic(GraphDatabase.class);
-
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
-			Config config = invocationOnMock.getArgument(2, Config.class);
-			return mockedDriver;
-		});
 
 		Properties info = new Properties();
 		info.setProperty("encryption","XX");
-		Driver driver = new BoltDriver();
+		Driver driver = new BoltDriver((routingUris, config, authToken, props) -> mockedDriver);
 		driver.connect(COMPLETE_VALID_URL, info);
 	}
 
 	@Test public void shouldConfigureLeakedSessionsLogging() throws SQLException, URISyntaxException {
-		PowerMockito.mockStatic(GraphDatabase.class);
-
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
-			Config config = invocationOnMock.getArgument(2, Config.class);
-
-			assertEquals(true, config.logLeakedSessions());;
-
+		Properties info = new Properties();
+		info.setProperty("leaked.sessions.logging","true");
+		AtomicBoolean called = new AtomicBoolean(false);
+		Driver driver = new BoltDriver((routingUris, config, authToken, props) -> {
+			assertTrue(config.logLeakedSessions());;
+			assertTrue(called.compareAndSet(false, true));
 			return mockedDriver;
 		});
 
-		Properties info = new Properties();
-		info.setProperty("leaked.sessions.logging","true");
-		Driver driver = new BoltDriver();
 		driver.connect(COMPLETE_VALID_URL, info);
+
+		assertTrue(called.get());
 	}
 
 	@Test
-	public void shouldRefuseLeakedSessionsLogging() throws SQLException, URISyntaxException {
+	public void shouldRefuseLeakedSessionsLogging() throws SQLException {
 		expectedEx.expect(SQLException.class);
 		expectedEx.expectMessage("leaked.sessions.logging: XX is not a boolean");
-		PowerMockito.mockStatic(GraphDatabase.class);
-
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
-			Config config = invocationOnMock.getArgument(2, Config.class);
-			return mockedDriver;
-		});
-
 		Properties info = new Properties();
 		info.setProperty("leaked.sessions.logging","XX");
-		Driver driver = new BoltDriver();
-		driver.connect(COMPLETE_VALID_URL, info);
-	}
-
-	@Test public void shouldConfigureLoadBalancingStrategy_LEAST_CONNECTED() throws SQLException, URISyntaxException {
-		PowerMockito.mockStatic(GraphDatabase.class);
+		Driver driver = new BoltDriver((routingUris, config, authToken, props) -> mockedDriver);
 
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
-			Config config = invocationOnMock.getArgument(2, Config.class);
-
-			// assertEquals(Config.LoadBalancingStrategy.LEAST_CONNECTED, config.loadBalancingStrategy());
-
-			return mockedDriver;
-		});
-
-		Properties info = new Properties();
-		info.setProperty("load.balancing.strategy","LEAST_CONNECTED");
-		Driver driver = new BoltDriver();
-		driver.connect(COMPLETE_VALID_URL, info);
-	}
-
-	@Test public void shouldConfigureLoadBalancingStrategy_ROUND_ROBIN() throws SQLException, URISyntaxException {
-		PowerMockito.mockStatic(GraphDatabase.class);
-
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
-			Config config = invocationOnMock.getArgument(2, Config.class);
-			// assertEquals(Config.LoadBalancingStrategy.ROUND_ROBIN, config.loadBalancingStrategy());
-
-			return mockedDriver;
-		});
-
-		Properties info = new Properties();
-		info.setProperty("load.balancing.strategy","ROUND_ROBIN");
-		Driver driver = new BoltDriver();
 		driver.connect(COMPLETE_VALID_URL, info);
 	}
 
-//	@Test
-//	public void shouldRefuseLoadBalancingStrategy() throws SQLException, URISyntaxException {
-//		expectedEx.expect(SQLException.class);
-//		expectedEx.expectMessage("load.balancing.strategy: XX is not a load balancing strategy");
-//		PowerMockito.mockStatic(GraphDatabase.class);
-//
-//		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
-//			Config config = invocationOnMock.getArgument(2, Config.class);
-//			return mockedDriver;
-//		});
-//
-//		Properties info = new Properties();
-//		info.setProperty("load.balancing.strategy","XX");
-//		Driver driver = new BoltDriver();
-//		driver.connect(COMPLETE_VALID_URL, info);
-//	}
-
 	@Test public void shouldConfigureMaxConnectionLifetime() throws SQLException, URISyntaxException {
-		PowerMockito.mockStatic(GraphDatabase.class);
-
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
-			Config config = invocationOnMock.getArgument(2, Config.class);
-
+		Properties info = new Properties();
+		info.setProperty("max.connection.lifetime","123000");
+		AtomicBoolean called = new AtomicBoolean(false);
+		Driver driver = new BoltDriver((routingUris, config, authToken, props) -> {
 			assertEquals(123_000, config.maxConnectionLifetimeMillis());
-
+			assertTrue(called.compareAndSet(false, true));
 			return mockedDriver;
 		});
 
-		Properties info = new Properties();
-		info.setProperty("max.connection.lifetime","123000");
-		Driver driver = new BoltDriver();
 		driver.connect(COMPLETE_VALID_URL, info);
+
+		assertTrue(called.get());
 	}
 
 	@Test
 	public void shouldRefuseMaxConnectionLifetime() throws SQLException, URISyntaxException {
 		expectedEx.expect(SQLException.class);
 		expectedEx.expectMessage("max.connection.lifetime: XX is not a number");
-		PowerMockito.mockStatic(GraphDatabase.class);
-
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
-			Config config = invocationOnMock.getArgument(2, Config.class);
-			return mockedDriver;
-		});
-
 		Properties info = new Properties();
 		info.setProperty("max.connection.lifetime","XX");
-		Driver driver = new BoltDriver();
+		Driver driver = new BoltDriver((routingUris, config, authToken, props) -> mockedDriver);
+
 		driver.connect(COMPLETE_VALID_URL, info);
 	}
 
 	@Test public void shouldConfigureMaxConnectionPoolSize() throws SQLException, URISyntaxException {
-		PowerMockito.mockStatic(GraphDatabase.class);
-
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
-			Config config = invocationOnMock.getArgument(2, Config.class);
-
+		Properties info = new Properties();
+		info.setProperty("max.connection.poolsize","3");
+		AtomicBoolean called = new AtomicBoolean(false);
+		Driver driver = new BoltDriver((routingUris, config, authToken, props) -> {
 			assertEquals(3, config.maxConnectionPoolSize());
-
+			assertTrue(called.compareAndSet(false, true));
 			return mockedDriver;
 		});
 
-		Properties info = new Properties();
-		info.setProperty("max.connection.poolsize","3");
-		Driver driver = new BoltDriver();
 		driver.connect(COMPLETE_VALID_URL, info);
+
+		assertTrue(called.get());
 	}
 
 	@Test
-	public void shouldRefuseMaxConnectionPoolSize() throws SQLException, URISyntaxException {
+	public void shouldRefuseMaxConnectionPoolSize() throws SQLException {
 		expectedEx.expect(SQLException.class);
 		expectedEx.expectMessage("max.connection.poolsize: XX is not a number");
-		PowerMockito.mockStatic(GraphDatabase.class);
-
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
-			Config config = invocationOnMock.getArgument(2, Config.class);
-			return mockedDriver;
-		});
-
 		Properties info = new Properties();
 		info.setProperty("max.connection.poolsize","XX");
-		Driver driver = new BoltDriver();
+		Driver driver = new BoltDriver((routingUris, config, authToken, props) -> mockedDriver);
+
 		driver.connect(COMPLETE_VALID_URL, info);
 	}
 
-	@Test public void shouldConfigure_TRUST_SYSTEM_CA_SIGNED_CERTIFICATES() throws SQLException, URISyntaxException {
-		PowerMockito.mockStatic(GraphDatabase.class);
-
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
-			Config config = invocationOnMock.getArgument(2, Config.class);
+	@Test public void shouldConfigure_TRUST_SYSTEM_CA_SIGNED_CERTIFICATES() throws SQLException {
+		Properties info = new Properties();
+		info.setProperty("trust.strategy","TRUST_SYSTEM_CA_SIGNED_CERTIFICATES");
 
+		AtomicBoolean called = new AtomicBoolean(false);
+		Driver driver = new BoltDriver((routingUris, config, authToken, props) -> {
 			assertEquals(Config.TrustStrategy.trustSystemCertificates().strategy(), config.trustStrategy().strategy());
-
+			assertTrue(called.compareAndSet(false, true));
 			return mockedDriver;
 		});
 
-		Properties info = new Properties();
-		info.setProperty("trust.strategy","TRUST_SYSTEM_CA_SIGNED_CERTIFICATES");
-		Driver driver = new BoltDriver();
 		driver.connect(COMPLETE_VALID_URL, info);
+
+		assertTrue(called.get());
 	}
 
 	@Test public void shouldConfigure_TRUST_CUSTOM_CA_SIGNED_CERTIFICATES() throws SQLException, URISyntaxException {
-		PowerMockito.mockStatic(GraphDatabase.class);
-
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
-			Config config = invocationOnMock.getArgument(2, Config.class);
-
-			assertEquals(Config.TrustStrategy.trustCustomCertificateSignedBy(new File("empty.txt")).strategy(), config.trustStrategy().strategy());
-
-			return mockedDriver;
-		});
-
 		Properties info = new Properties();
 		info.setProperty("trust.strategy","TRUST_CUSTOM_CA_SIGNED_CERTIFICATES");
 		info.setProperty("trusted.certificate.file","empty.txt");
-		Driver driver = new BoltDriver();
-		driver.connect(COMPLETE_VALID_URL, info);
-	}
-
-//	@Test public void shouldConfigure_TRUST_ON_FIRST_USE() throws SQLException, URISyntaxException {
-//		PowerMockito.mockStatic(GraphDatabase.class);
-//
-//		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
-//			Config config = invocationOnMock.getArgument(2, Config.class);
-//
-//			// assertEquals(Config.TrustStrategy.trustOnFirstUse(new File("empty.txt")).strategy(), config.trustStrategy().strategy());
-//
-//			return mockedDriver;
-//		});
-//
-//		Properties info = new Properties();
-//		info.setProperty("trust.strategy","TRUST_ON_FIRST_USE");
-//		info.setProperty("trusted.certificate.file","empty.txt");
-//		Driver driver = new BoltDriver();
-//		driver.connect(COMPLETE_VALID_URL, info);
-//	}
-
-	@Test
-	public void shouldRefuseTrustStrategy() throws SQLException, URISyntaxException {
-		expectedEx.expect(SQLException.class);
-		expectedEx.expectMessage("Invalid value for trust.strategy param.");
-		PowerMockito.mockStatic(GraphDatabase.class);
-
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
-			Config config = invocationOnMock.getArgument(2, Config.class);
+		AtomicBoolean called = new AtomicBoolean(false);
+		Driver driver = new BoltDriver((routingUris, config, authToken, props) -> {
+			assertTrue(called.compareAndSet(false, true));
+			assertEquals(Config.TrustStrategy.trustCustomCertificateSignedBy(new File("empty.txt")).strategy(), config.trustStrategy().strategy());
 			return mockedDriver;
 		});
 
-		Properties info = new Properties();
-		info.setProperty("trust.strategy","XX");
-		Driver driver = new BoltDriver();
 		driver.connect(COMPLETE_VALID_URL, info);
-	}
-
-	@Test
-	public void shouldRefuseTrustStrategyCertificate() throws SQLException, URISyntaxException {
-		expectedEx.expect(SQLException.class);
-		expectedEx.expectMessage("Missing parameter 'trusted.certificate.file' : A FILE IS REQUIRED");
-		PowerMockito.mockStatic(GraphDatabase.class);
-
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
-			Config config = invocationOnMock.getArgument(2, Config.class);
-			return mockedDriver;
-		});
 
-		Properties info = new Properties();
-		info.setProperty("trust.strategy","TRUST_CUSTOM_CA_SIGNED_CERTIFICATES");
-		Driver driver = new BoltDriver();
-		driver.connect(COMPLETE_VALID_URL, info);
+		assertTrue(called.get());
 	}
 
 	@Test
-	public void shouldConfigureMaxTransactionRetryTime() throws SQLException, URISyntaxException {
-		PowerMockito.mockStatic(GraphDatabase.class);
-
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(BOLT_URL)), Mockito.eq(AuthTokens.none()), any(Config.class))).thenAnswer(invocationOnMock -> {
-			Config config = invocationOnMock.getArgument(2, Config.class);
-
-			// retrySettings is not visible...
-
-			return mockedDriver;
-		});
+	public void shouldRefuseTrustStrategy() throws SQLException {
+		expectedEx.expect(SQLException.class);
+		expectedEx.expectMessage("Invalid value for trust.strategy param.");
 
 		Properties info = new Properties();
-		info.setProperty("max.transaction.retry.time","1000");//milliseconds
-		Driver driver = new BoltDriver();
+		info.setProperty("trust.strategy","XX");
+		Driver driver = new BoltDriver((routingUris, config, authToken, props) -> mockedDriver);
 		driver.connect(COMPLETE_VALID_URL, info);
 	}
-
 }
diff --git a/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/BoltNeo4jDriverUrlTest.java b/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/BoltNeo4jDriverUrlTest.java
index ca2c3be7..29b013e8 100644
--- a/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/BoltNeo4jDriverUrlTest.java
+++ b/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/BoltNeo4jDriverUrlTest.java
@@ -28,15 +28,13 @@ import org.junit.rules.ExpectedException;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 import org.mockito.Mockito;
+import org.neo4j.driver.AuthToken;
 import org.neo4j.driver.AuthTokens;
 import org.neo4j.driver.Config;
+import org.neo4j.driver.Driver;
 import org.neo4j.driver.GraphDatabase;
 import org.neo4j.jdbc.Neo4jDriver;
 import org.neo4j.jdbc.bolt.utils.Mocker;
-import org.powermock.api.mockito.PowerMockito;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-import org.powermock.modules.junit4.PowerMockRunnerDelegate;
 
 import java.net.URI;
 import java.net.URISyntaxException;
@@ -44,6 +42,7 @@ import java.sql.Connection;
 import java.sql.SQLException;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Properties;
 
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
@@ -53,9 +52,7 @@ import static org.mockito.Matchers.any;
  * @author AgileLARUS
  * @since 3.0.0
  */
-@RunWith(PowerMockRunner.class)
-@PrepareForTest({GraphDatabase.class, Config.TrustStrategy.class, AuthTokens.class})
-@PowerMockRunnerDelegate(Parameterized.class)
+@RunWith(Parameterized.class)
 public class BoltNeo4jDriverUrlTest {
 
 	@Rule public ExpectedException expectedEx = ExpectedException.none();
@@ -66,7 +63,7 @@ public class BoltNeo4jDriverUrlTest {
 	private static org.neo4j.driver.Driver mockedDriver;
 
 	@Parameterized.Parameters
-	public static Iterable<? extends Object> data() {
+	public static Iterable<?> data() {
 		return Arrays.asList("jdbc:neo4j:bolt://test", "jdbc:neo4j:bolt+s://test", "jdbc:neo4j:bolt+ssc://test");
 	}
 
@@ -77,7 +74,6 @@ public class BoltNeo4jDriverUrlTest {
 
 	@After
 	public void prepare() {
-		BoltDriver.clearCache();
 	}
 
 	private String getBoltUrl() {
@@ -89,16 +85,13 @@ public class BoltNeo4jDriverUrlTest {
 	}
 
 	@Test public void shouldConnectCreateConnection() throws SQLException, URISyntaxException {
-		PowerMockito.mockStatic(GraphDatabase.class);
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(getBoltUrl())), Mockito.eq(AuthTokens.none()), any(Config.class))).thenReturn(mockedDriver);
-
-		Neo4jDriver driver = new BoltDriver();
+		Neo4jDriver driver = new BoltDriver((routingUris, config, authToken, info) -> mockedDriver);
 		Connection connection = driver.connect(completeValidUrl, null);
 		assertNotNull(connection);
 	}
 
 	@Test public void shouldAcceptURL() throws SQLException {
-		Neo4jDriver driver = new BoltDriver();
+		Neo4jDriver driver = new BoltDriver((routingUris, config, authToken, info) -> mockedDriver);
 		assertTrue(driver.acceptsURL(getPrefix() + "://localhost:7687"));
 		assertTrue(driver.acceptsURL(getPrefix() + "://localhost:7687/"));
 		assertTrue(driver.acceptsURL(getPrefix() + "://192.168.0.1:7687"));
diff --git a/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/BoltNeo4jPreparedStatementTest.java b/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/BoltNeo4jPreparedStatementTest.java
index 092c5e8a..a1a73a9f 100644
--- a/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/BoltNeo4jPreparedStatementTest.java
+++ b/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/BoltNeo4jPreparedStatementTest.java
@@ -23,112 +23,120 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.junit.runner.RunWith;
 import org.mockito.Mockito;
 import org.neo4j.driver.Result;
 import org.neo4j.driver.Transaction;
 import org.neo4j.driver.summary.ResultSummary;
 import org.neo4j.driver.summary.SummaryCounters;
-import org.neo4j.jdbc.Neo4jStatement;
 import org.neo4j.jdbc.bolt.data.StatementData;
 import org.neo4j.jdbc.bolt.impl.BoltNeo4jConnectionImpl;
 import org.neo4j.jdbc.bolt.utils.Mocker;
 import org.neo4j.jdbc.impl.ListArray;
-import org.neo4j.jdbc.utils.PreparedStatementBuilder;
-import org.powermock.api.mockito.PowerMockito;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-import org.powermock.reflect.Whitebox;
 
-import java.sql.*;
+import java.sql.BatchUpdateException;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
-
-import static java.sql.Types.*;
-import static org.junit.Assert.*;
-import static org.mockito.Mockito.*;
-import static org.mockito.Mockito.doNothing;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static java.sql.Types.ARRAY;
+import static java.sql.Types.BLOB;
+import static java.sql.Types.CLOB;
+import static java.sql.Types.DATALINK;
+import static java.sql.Types.INTEGER;
+import static java.sql.Types.JAVA_OBJECT;
+import static java.sql.Types.LONGNVARCHAR;
+import static java.sql.Types.NCHAR;
+import static java.sql.Types.NCLOB;
+import static java.sql.Types.NULL;
+import static java.sql.Types.NVARCHAR;
+import static java.sql.Types.REF;
+import static java.sql.Types.ROWID;
+import static java.sql.Types.SQLXML;
+import static java.sql.Types.STRUCT;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.mockito.Mockito.anyMap;
+import static org.mockito.Mockito.anyString;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
-import static org.neo4j.jdbc.bolt.utils.Mocker.*;
-import static org.powermock.api.mockito.PowerMockito.*;
+import static org.neo4j.jdbc.bolt.utils.Mocker.mockConnectionClosed;
+import static org.neo4j.jdbc.bolt.utils.Mocker.mockOpenConnection;
+import static org.neo4j.jdbc.bolt.utils.Mocker.mockOpenConnectionWithResult;
+import static org.neo4j.jdbc.bolt.utils.Mocker.mockResultWithUpdateCount;
 
 /**
  * @author AgileLARUS
  * @since 3.0.0
  */
-@RunWith(PowerMockRunner.class)
-@PrepareForTest({ BoltNeo4jPreparedStatement.class, BoltNeo4jResultSet.class })
-
 public class BoltNeo4jPreparedStatementTest {
 
 	@Rule
 	public ExpectedException expectedEx = ExpectedException.none();
 
-	private PreparedStatement preparedStatementOneParam;
-	private PreparedStatement preparedStatementTwoParams;
-
-	private BoltNeo4jResultSet mockedRS;
+	private BoltNeo4jPreparedStatement preparedStatementOneParam;
+	private BoltNeo4jPreparedStatement preparedStatementTwoParams;
 
-	@Before public void interceptBoltResultSetConstructor() throws Exception {
-		preparedStatementOneParam = mock(BoltNeo4jPreparedStatement.class, CALLS_REAL_METHODS);
-		Whitebox.setInternalState(preparedStatementOneParam, "batchStatements", new ArrayList<>());
-		String statementOneParam = "MATCH n RETURN n WHERE n.name = ?";
-		String replacedStatementOneParam = PreparedStatementBuilder.replacePlaceholders(statementOneParam);
-		Whitebox.setInternalState(preparedStatementOneParam, "statement", replacedStatementOneParam);
-		Whitebox.setInternalState(preparedStatementOneParam, "connection", mockConnectionOpenWithTransactionThatReturns(null));
-		Whitebox.setInternalState(preparedStatementOneParam, "parametersNumber", PreparedStatementBuilder.namedParameterCount(replacedStatementOneParam));
-		Whitebox.setInternalState(preparedStatementOneParam, "parameters", new HashMap<>());
+	private BoltNeo4jResultSet expectedResultSet;
+	private ResultSetFactory resultSetFactory;
 
-		preparedStatementTwoParams = mock(BoltNeo4jPreparedStatement.class, CALLS_REAL_METHODS);
-		Whitebox.setInternalState(preparedStatementTwoParams, "batchStatements", new ArrayList<>());
-		String statementTwoParams = "MATCH n RETURN n WHERE n.name = ? AND n.surname = ?";
-		String replacedStatementTwoParams = PreparedStatementBuilder.replacePlaceholders(statementTwoParams);
-		Whitebox.setInternalState(preparedStatementTwoParams, "statement", replacedStatementTwoParams);
-		Whitebox.setInternalState(preparedStatementTwoParams, "connection", mockConnectionOpenWithTransactionThatReturns(null));
-		Whitebox.setInternalState(preparedStatementTwoParams, "parametersNumber", PreparedStatementBuilder.namedParameterCount(replacedStatementTwoParams));
-		Whitebox.setInternalState(preparedStatementTwoParams, "parameters", new HashMap<>());
-
-		/*this.preparedStatementOneParam = BoltNeo4jPreparedStatement.newInstance(mockConnectionOpenWithTransactionThatReturns(null),
-				"MATCH n RETURN n WHERE n.name = ?");
-		this.preparedStatementTwoParams = BoltNeo4jPreparedStatement.newInstance(mockConnectionOpenWithTransactionThatReturns(null),
-				"MATCH n RETURN n WHERE n.name = ? AND n.surname = ?");*/
-
-		this.mockedRS = mock(BoltNeo4jResultSet.class);
-		doNothing().when(this.mockedRS).close();
-		mockStatic(BoltNeo4jResultSet.class);
-		PowerMockito.when(BoltNeo4jResultSet.newInstance(anyBoolean(), any(Neo4jStatement.class), any(Result.class))).thenReturn(mockedRS);
+	@Before public void interceptBoltResultSetConstructor() throws SQLException {
+		expectedResultSet = mock(BoltNeo4jResultSet.class);
+		resultSetFactory = (debug, statement, iterator, params) -> expectedResultSet;
+		preparedStatementOneParam = new BoltNeo4jPreparedStatement(mockOpenConnection(), resultSetFactory, "RETURN $1");
+		preparedStatementTwoParams = new BoltNeo4jPreparedStatement(mockOpenConnection(), resultSetFactory, "RETURN $1+$2");
 	}
 
 	/*------------------------------*/
 	/*             close            */
 	/*------------------------------*/
 	@Test public void closeShouldCloseExistingResultSet() throws Exception {
-		Result mockedSR = mock(Result.class);
-		PreparedStatement prStatement = BoltNeo4jPreparedStatement.newInstance(false, mockConnectionOpenWithTransactionThatReturns(mockedSR), "");
+		Result mockedDriverResult = mock(Result.class);
+		BoltNeo4jConnectionImpl connection = mockOpenConnectionWithResult(mockedDriverResult);
+		BoltNeo4jPreparedStatement prStatement = new BoltNeo4jPreparedStatement(connection, resultSetFactory, "");
 		final ResultSet resultSet = prStatement.executeQuery();
+
 		prStatement.close();
 
-		verify(resultSet, times(1)).close();
+		assertSame(resultSet, expectedResultSet);
+		verify(expectedResultSet, times(1)).close();
 	}
 
 	@Test public void closeShouldNotCallCloseOnAnyResultSet() throws Exception {
-		PreparedStatement prStatement = BoltNeo4jPreparedStatement.newInstance(false, mockConnectionOpenWithTransactionThatReturns(null), "");
+		PreparedStatement prStatement = BoltNeo4jPreparedStatement.newInstance(false, mockOpenConnectionWithResult(null), "");
+
 		prStatement.close();
 
-		verify(this.mockedRS, never()).close();
+		verify(expectedResultSet, never()).close();
 	}
 
 	@Test public void closeMultipleTimesIsNOOP() throws Exception {
-		Result mockedSR = mock(Result.class);
-		PreparedStatement prStatement = BoltNeo4jPreparedStatement.newInstance(false, mockConnectionOpenWithTransactionThatReturns(mockedSR), "");
+		Result mockedDriverResult = mock(Result.class);
+		BoltNeo4jConnectionImpl connection = mockOpenConnectionWithResult(mockedDriverResult);
+		BoltNeo4jPreparedStatement prStatement = new BoltNeo4jPreparedStatement(connection, resultSetFactory, "");;
 		final ResultSet resultSet = prStatement.executeQuery();
+
 		prStatement.close();
 		prStatement.close();
 		prStatement.close();
 
+		assertSame(resultSet, expectedResultSet);
 		verify(resultSet, times(1)).close();
 	}
 
@@ -136,7 +144,8 @@ public class BoltNeo4jPreparedStatementTest {
 	/*           isClosed           */
 	/*------------------------------*/
 	@Test public void isClosedShouldReturnFalseWhenCreated() throws SQLException {
-		PreparedStatement prStatement = BoltNeo4jPreparedStatement.newInstance(false, mockConnectionOpen(), "");
+		BoltNeo4jConnectionImpl connection = mockOpenConnection();
+		PreparedStatement prStatement = new BoltNeo4jPreparedStatement(connection, resultSetFactory, "");
 
 		assertFalse(prStatement.isClosed());
 	}
@@ -147,34 +156,30 @@ public class BoltNeo4jPreparedStatementTest {
 
 	@Test public void setIntShouldInsertTheCorrectIntegerValue() throws SQLException {
 		this.preparedStatementOneParam.setInt(1, 10);
-		HashMap<String, Object> value = Whitebox.getInternalState(this.preparedStatementOneParam, "parameters");
-		assertEquals(10, value.get("1"));
+		assertEquals(10, this.preparedStatementOneParam.getParameters().get("1"));
 
 		this.preparedStatementTwoParams.setInt(2, 125);
-		value = Whitebox.getInternalState(this.preparedStatementTwoParams, "parameters");
-		assertEquals(125, value.get("2"));
+		assertEquals(125, this.preparedStatementTwoParams.getParameters().get("2"));
 	}
 
 	@Test public void setIntShouldOverrideOldValue() throws SQLException {
 		this.preparedStatementOneParam.setInt(1, 10);
-		HashMap<String, Object> value = Whitebox.getInternalState(this.preparedStatementOneParam, "parameters");
-		assertEquals(10, value.get("1"));
-
+		assertEquals(10, this.preparedStatementOneParam.getParameters().get("1"));
 		this.preparedStatementOneParam.setInt(1, 99);
-		value = Whitebox.getInternalState(this.preparedStatementOneParam, "parameters");
-		assertEquals(99, value.get("1"));
+
+		assertEquals(99, this.preparedStatementOneParam.getParameters().get("1"));
 	}
 
 	@Test public void setIntShouldThrowExceptionIfIndexDoesNotCorrespondToParameterMarker() throws SQLException {
 		expectedEx.expect(SQLException.class);
 
-		this.preparedStatementOneParam.setInt(99, 10);
+		this.preparedStatementOneParam.setInt(2, 10);
 	}
 
 	@Test public void setIntShouldThrowExceptionIfIndexDoesNotCorrespondToParameterMarkerTwoParams() throws SQLException {
 		expectedEx.expect(SQLException.class);
 
-		this.preparedStatementTwoParams.setInt(99, 10);
+		this.preparedStatementTwoParams.setInt(3, 10);
 	}
 
 	@Test public void setIntShouldThrowExceptionIfClosedPreparedStatement() throws SQLException {
@@ -190,28 +195,24 @@ public class BoltNeo4jPreparedStatementTest {
 
 	@Test public void setLongShouldInsertTheCorrectLongValue() throws SQLException {
 		this.preparedStatementOneParam.setLong(1, 10L);
-		HashMap<String, Object> value = Whitebox.getInternalState(this.preparedStatementOneParam, "parameters");
-		assertEquals(10L, value.get("1"));
+		assertEquals(10L, preparedStatementOneParam.getParameters().get("1"));
 
 		this.preparedStatementTwoParams.setLong(2, 125L);
-		value = Whitebox.getInternalState(this.preparedStatementTwoParams, "parameters");
-		assertEquals(125L, value.get("2"));
+		assertEquals(125L, preparedStatementTwoParams.getParameters().get("2"));
 	}
 
 	@Test public void setLongShouldOverrideOldValue() throws SQLException {
 		this.preparedStatementOneParam.setLong(1, 10L);
-		HashMap<String, Object> value = Whitebox.getInternalState(this.preparedStatementOneParam, "parameters");
-		assertEquals(10L, value.get("1"));
-
+		assertEquals(10L, preparedStatementOneParam.getParameters().get("1"));
 		this.preparedStatementOneParam.setLong(1, 99L);
-		value = Whitebox.getInternalState(this.preparedStatementOneParam, "parameters");
-		assertEquals(99L, value.get("1"));
+
+		assertEquals(99L, preparedStatementOneParam.getParameters().get("1"));
 	}
 
 	@Test public void setLongShouldThrowExceptionIfIndexDoesNotCorrespondToParameterMarker() throws SQLException {
 		expectedEx.expect(SQLException.class);
 
-		this.preparedStatementOneParam.setLong(99, 10L);
+		this.preparedStatementOneParam.setLong(2, 10L);
 	}
 
 	@Test public void setLongShouldThrowExceptionIfClosedPreparedStatement() throws SQLException {
@@ -227,22 +228,18 @@ public class BoltNeo4jPreparedStatementTest {
 
 	@Test public void setFloatShouldInsertTheCorrectFloatValue() throws SQLException {
 		this.preparedStatementOneParam.setFloat(1, 10.5F);
-		HashMap<String, Object> value = Whitebox.getInternalState(this.preparedStatementOneParam, "parameters");
-		assertEquals(10.5F, value.get("1"));
+		assertEquals(10.5F, preparedStatementOneParam.getParameters().get("1"));
 
 		this.preparedStatementTwoParams.setFloat(2, 125.5F);
-		value = Whitebox.getInternalState(this.preparedStatementTwoParams, "parameters");
-		assertEquals(125.5F, value.get("2"));
+		assertEquals(125.5F, preparedStatementTwoParams.getParameters().get("2"));
 	}
 
 	@Test public void setFloatShouldOverrideOldValue() throws SQLException {
 		this.preparedStatementOneParam.setFloat(1, 10.5F);
-		HashMap<String, Object> value = Whitebox.getInternalState(this.preparedStatementOneParam, "parameters");
-		assertEquals(10.5F, value.get("1"));
+		assertEquals(10.5F, preparedStatementOneParam.getParameters().get("1"));
 
 		this.preparedStatementOneParam.setFloat(1, 55.5F);
-		value = Whitebox.getInternalState(this.preparedStatementOneParam, "parameters");
-		assertEquals(55.5F, value.get("1"));
+		assertEquals(55.5F, preparedStatementOneParam.getParameters().get("1"));
 	}
 
 	@Test public void setFloatShouldThrowExceptionIfIndexDoesNotCorrespondToParameterMarker() throws SQLException {
@@ -264,22 +261,18 @@ public class BoltNeo4jPreparedStatementTest {
 
 	@Test public void setDoubleShouldInsertTheCorrectDoubleValue() throws SQLException {
 		this.preparedStatementOneParam.setDouble(1, 10.5);
-		HashMap<String, Object> value = Whitebox.getInternalState(this.preparedStatementOneParam, "parameters");
-		assertEquals(10.5, value.get("1"));
+		assertEquals(10.5, preparedStatementOneParam.getParameters().get("1"));
 
 		this.preparedStatementTwoParams.setDouble(2, 125.5);
-		value = Whitebox.getInternalState(this.preparedStatementTwoParams, "parameters");
-		assertEquals(125.5, value.get("2"));
+		assertEquals(125.5, preparedStatementTwoParams.getParameters().get("2"));
 	}
 
 	@Test public void setDoubleShouldOverrideOldValue() throws SQLException {
 		this.preparedStatementOneParam.setDouble(1, 10.5);
-		HashMap<String, Object> value = Whitebox.getInternalState(this.preparedStatementOneParam, "parameters");
-		assertEquals(10.5, value.get("1"));
-
+		assertEquals(10.5, preparedStatementOneParam.getParameters().get("1"));
 		this.preparedStatementOneParam.setDouble(1, 55.5);
-		value = Whitebox.getInternalState(this.preparedStatementOneParam, "parameters");
-		assertEquals(55.5, value.get("1"));
+
+		assertEquals(55.5, preparedStatementOneParam.getParameters().get("1"));
 	}
 
 	@Test public void setDoubleShouldThrowExceptionIfIndexDoesNotCorrespondToParameterMarker() throws SQLException {
@@ -301,22 +294,18 @@ public class BoltNeo4jPreparedStatementTest {
 
 	@Test public void setShortShouldInsertTheCorrectShortValue() throws SQLException {
 		this.preparedStatementOneParam.setShort(1, (short) 10);
-		HashMap<String, Object> value = Whitebox.getInternalState(this.preparedStatementOneParam, "parameters");
-		assertEquals((short) 10, value.get("1"));
+		assertEquals((short) 10, preparedStatementOneParam.getParameters().get("1"));
 
 		this.preparedStatementTwoParams.setShort(2, (short) 125);
-		value = Whitebox.getInternalState(this.preparedStatementTwoParams, "parameters");
-		assertEquals((short) 125, value.get("2"));
+		assertEquals((short) 125, preparedStatementTwoParams.getParameters().get("2"));
 	}
 
 	@Test public void setShortShouldOverrideOldValue() throws SQLException {
 		this.preparedStatementOneParam.setShort(1, (short) 10);
-		HashMap<String, Object> value = Whitebox.getInternalState(this.preparedStatementOneParam, "parameters");
-		assertEquals((short) 10, value.get("1"));
-
+		assertEquals((short) 10, preparedStatementOneParam.getParameters().get("1"));
 		this.preparedStatementOneParam.setShort(1, (short) 20);
-		value = Whitebox.getInternalState(this.preparedStatementOneParam, "parameters");
-		assertEquals((short) 20, value.get("1"));
+
+		assertEquals((short) 20, preparedStatementOneParam.getParameters().get("1"));
 	}
 
 	@Test public void setShortShouldThrowExceptionIfIndexDoesNotCorrespondToParameterMarker() throws SQLException {
@@ -338,22 +327,18 @@ public class BoltNeo4jPreparedStatementTest {
 
 	@Test public void setStringShouldInsertTheCorrectStringValue() throws SQLException {
 		this.preparedStatementOneParam.setString(1, "string");
-		HashMap<String, Object> value = Whitebox.getInternalState(this.preparedStatementOneParam, "parameters");
-		assertEquals("string", value.get("1"));
+		assertEquals("string", preparedStatementOneParam.getParameters().get("1"));
 
 		this.preparedStatementTwoParams.setString(2, "text");
-		value = Whitebox.getInternalState(this.preparedStatementTwoParams, "parameters");
-		assertEquals("text", value.get("2"));
+		assertEquals("text", preparedStatementTwoParams.getParameters().get("2"));
 	}
 
 	@Test public void setStringShouldOverrideOldValue() throws SQLException {
 		this.preparedStatementOneParam.setString(1, "string");
-		HashMap<String, Object> value = Whitebox.getInternalState(this.preparedStatementOneParam, "parameters");
-		assertEquals("string", value.get("1"));
-
+		assertEquals("string", preparedStatementOneParam.getParameters().get("1"));
 		this.preparedStatementOneParam.setString(1, "otherString");
-		value = Whitebox.getInternalState(this.preparedStatementOneParam, "parameters");
-		assertEquals("otherString", value.get("1"));
+
+		assertEquals("otherString", preparedStatementOneParam.getParameters().get("1"));
 	}
 
 	@Test public void setStringShouldThrowExceptionIfIndexDoesNotCorrespondToParameterMarker() throws SQLException {
@@ -375,12 +360,10 @@ public class BoltNeo4jPreparedStatementTest {
 
 	@Test public void setNullShouldInsertTheCorrectNullValue() throws SQLException {
 		this.preparedStatementOneParam.setNull(1, NULL);
-		HashMap<String, Object> value = Whitebox.getInternalState(this.preparedStatementOneParam, "parameters");
-		assertEquals(null, value.get("1"));
+		assertNull(preparedStatementOneParam.getParameters().get("1"));
 
 		this.preparedStatementTwoParams.setNull(2, NULL);
-		value = Whitebox.getInternalState(this.preparedStatementTwoParams, "parameters");
-		assertEquals(null, value.get("2"));
+		assertNull(preparedStatementTwoParams.getParameters().get("2"));
 	}
 
 	@Test public void setNullShouldThrowExceptionIfIndexDoesNotCorrespondToParameterMarker() throws SQLException {
@@ -466,8 +449,7 @@ public class BoltNeo4jPreparedStatementTest {
 	/*------------------------------*/
 
 	@Test public void clearParametersShouldDeleteAllParameters() throws SQLException {
-		HashMap<String, Object> value = Whitebox.getInternalState(this.preparedStatementOneParam, "parameters");
-
+		Map<String, Object> value = preparedStatementOneParam.getParameters();
 		value.put("1", "string");
 		assertEquals(1, value.size());
 
@@ -489,22 +471,18 @@ public class BoltNeo4jPreparedStatementTest {
 
 	@Test public void setBooleanShouldInsertTheCorrectBooleanValue() throws SQLException {
 		this.preparedStatementOneParam.setBoolean(1, true);
-		HashMap<String, Object> value = Whitebox.getInternalState(this.preparedStatementOneParam, "parameters");
-		assertEquals(true, value.get("1"));
+		assertEquals(true, preparedStatementOneParam.getParameters().get("1"));
 
 		this.preparedStatementTwoParams.setBoolean(2, false);
-		value = Whitebox.getInternalState(this.preparedStatementTwoParams, "parameters");
-		assertEquals(false, value.get("2"));
+		assertEquals(false, preparedStatementTwoParams.getParameters().get("2"));
 	}
 
 	@Test public void setBooleanShouldOverrideOldValue() throws SQLException {
 		this.preparedStatementOneParam.setBoolean(1, true);
-		HashMap<String, Object> value = Whitebox.getInternalState(this.preparedStatementOneParam, "parameters");
-		assertEquals(true, value.get("1"));
-
+		assertEquals(true, preparedStatementOneParam.getParameters().get("1"));
 		this.preparedStatementOneParam.setBoolean(1, false);
-		value = Whitebox.getInternalState(this.preparedStatementOneParam, "parameters");
-		assertEquals(false, value.get("1"));
+
+		assertEquals(false, preparedStatementOneParam.getParameters().get("1"));
 	}
 
 	@Test public void setBooleanShouldThrowExceptionIfIndexDoesNotCorrespondToParameterMarker() throws SQLException {
@@ -528,25 +506,21 @@ public class BoltNeo4jPreparedStatementTest {
 	@Test public void setObjectShouldInsertTheCorrectObjectValue() throws SQLException {
 		Object obj = new HashMap<>();
 		this.preparedStatementOneParam.setObject(1, obj);
-		HashMap<String, Object> value = Whitebox.getInternalState(this.preparedStatementOneParam, "parameters");
-		assertEquals(obj, value.get("1"));
+		assertEquals(obj, preparedStatementOneParam.getParameters().get("1"));
 
 		this.preparedStatementTwoParams.setObject(2, obj);
-		value = Whitebox.getInternalState(this.preparedStatementTwoParams, "parameters");
-		assertEquals(obj, value.get("2"));
+		assertEquals(obj, preparedStatementTwoParams.getParameters().get("2"));
 	}
 
 	@Test public void setObjectShouldOverrideOldValue() throws SQLException {
 		Object obj = new HashMap<>();
 		this.preparedStatementOneParam.setObject(1, obj);
-		HashMap<String, Object> value = Whitebox.getInternalState(this.preparedStatementOneParam, "parameters");
-		assertEquals(obj, value.get("1"));
+		assertEquals(obj, preparedStatementOneParam.getParameters().get("1"));
 
 		Object newObj = new ArrayList<>();
 		;
 		this.preparedStatementOneParam.setObject(1, newObj);
-		value = Whitebox.getInternalState(this.preparedStatementOneParam, "parameters");
-		assertEquals(newObj, value.get("1"));
+		assertEquals(newObj, preparedStatementOneParam.getParameters().get("1"));
 	}
 
 	@Test public void setObjectShouldThrowExceptionIfIndexDoesNotCorrespondToParameterMarker() throws SQLException {
@@ -573,12 +547,9 @@ public class BoltNeo4jPreparedStatementTest {
 	/*------------------------------*/
 
 	@Test public void getParameterMetaDataShouldReturnANewParameterMetaData() throws Exception {
-		whenNew(BoltNeo4jParameterMetaData.class).withAnyArguments().thenReturn(null);
-
-		this.preparedStatementOneParam.getParameterMetaData();
-
-		verifyNew(BoltNeo4jParameterMetaData.class).withArguments(this.preparedStatementOneParam);
+		BoltNeo4jParameterMetaData parameterMetaData = (BoltNeo4jParameterMetaData) preparedStatementOneParam.getParameterMetaData();
 
+		assertSame(preparedStatementOneParam, parameterMetaData.getPreparedStatement());
 	}
 
 	@Test public void getParameterMetaDataShouldThrowExceptionIfCalledOnClosedStatement() throws Exception {
@@ -632,20 +603,25 @@ public class BoltNeo4jPreparedStatementTest {
 	}
 
 	@Test public void executeQueryShouldReturnCorrectResultSetStructureConnectionNotAutocommit() throws Exception {
-		BoltNeo4jConnectionImpl mockConnection = mockConnectionOpenWithTransactionThatReturns(null);
-
-		PreparedStatement statement = BoltNeo4jPreparedStatement
-				.newInstance(false, mockConnection, "", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT);
+		int[] parameters = {ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT};
+		AtomicBoolean called = new AtomicBoolean(false);
+		PreparedStatement statement = new BoltNeo4jPreparedStatement(mockOpenConnectionWithResult(null), (debug, stmt, iterator, params) -> {
+			assertFalse(debug);
+			assertNotNull(stmt);
+			assertNull(iterator);
+			assertArrayEquals(parameters, params);
+			assertTrue(called.compareAndSet(false, true));
+			return expectedResultSet;
+		}, "RETURN 42", parameters);
 		statement.executeQuery();
 
-		verifyStatic(BoltNeo4jResultSet.class);
-		BoltNeo4jResultSet.newInstance(false, statement, null, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT);
+		assertTrue(called.get());
 	}
 
 	@Test public void executeQueryShouldThrowExceptionOnClosedStatement() throws SQLException {
 		expectedEx.expect(SQLException.class);
 
-		PreparedStatement statement = BoltNeo4jPreparedStatement.newInstance(false, mockConnectionOpen(), StatementData.STATEMENT_MATCH_ALL);
+		PreparedStatement statement = BoltNeo4jPreparedStatement.newInstance(false, mockOpenConnection(), StatementData.STATEMENT_MATCH_ALL);
 		statement.close();
 
 		statement.executeQuery();
@@ -665,7 +641,7 @@ public class BoltNeo4jPreparedStatementTest {
 		when(mockSummaryCounters.nodesDeleted()).thenReturn(0);
 
 		PreparedStatement statement = BoltNeo4jPreparedStatement
-				.newInstance(false, mockConnectionOpenWithTransactionThatReturns(mockResult), StatementData.STATEMENT_CREATE_TWO_PROPERTIES_PARAMETRIC,
+				.newInstance(false, mockOpenConnectionWithResult(mockResult), StatementData.STATEMENT_CREATE_TWO_PROPERTIES_PARAMETRIC,
 						ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT);
 		statement.setString(1, "test");
 		statement.setString(2, "test2");
@@ -675,7 +651,7 @@ public class BoltNeo4jPreparedStatementTest {
 	@Test public void executeUpdateShouldThrowExceptionOnClosedStatement() throws SQLException {
 		expectedEx.expect(SQLException.class);
 
-		PreparedStatement statement = BoltNeo4jPreparedStatement.newInstance(false, mockConnectionOpen(), StatementData.STATEMENT_MATCH_ALL);
+		PreparedStatement statement = BoltNeo4jPreparedStatement.newInstance(false, mockOpenConnection(), StatementData.STATEMENT_MATCH_ALL);
 		statement.close();
 
 		statement.executeUpdate();
@@ -694,7 +670,6 @@ public class BoltNeo4jPreparedStatementTest {
 	@Test public void executeShouldRunQuery() throws SQLException {
 		BoltNeo4jPreparedStatement statement = mock(BoltNeo4jPreparedStatement.class);
 		when(statement.executeQuery()).thenCallRealMethod();
-		Whitebox.setInternalState(statement, "statement", StatementData.STATEMENT_MATCH_ALL);
 
 		statement.execute();
 	}
@@ -710,7 +685,7 @@ public class BoltNeo4jPreparedStatementTest {
 		when(mockSummaryCounters.nodesDeleted()).thenReturn(0);
 
 		PreparedStatement statement = BoltNeo4jPreparedStatement
-				.newInstance(false, mockConnectionOpenWithTransactionThatReturns(mockResult), StatementData.STATEMENT_CREATE_TWO_PROPERTIES_PARAMETRIC,
+				.newInstance(false, mockOpenConnectionWithResult(mockResult), StatementData.STATEMENT_CREATE_TWO_PROPERTIES_PARAMETRIC,
 						ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT);
 		statement.setString(1, "test");
 		statement.setString(2, "test2");
@@ -720,7 +695,7 @@ public class BoltNeo4jPreparedStatementTest {
 	@Test public void executeShouldThrowExceptionOnQueryOnClosedStatement() throws SQLException {
 		expectedEx.expect(SQLException.class);
 
-		PreparedStatement statement = BoltNeo4jPreparedStatement.newInstance(false, mockConnectionOpen(), StatementData.STATEMENT_MATCH_ALL);
+		PreparedStatement statement = BoltNeo4jPreparedStatement.newInstance(false, mockOpenConnection(), StatementData.STATEMENT_MATCH_ALL);
 		statement.close();
 
 		statement.execute();
@@ -729,7 +704,7 @@ public class BoltNeo4jPreparedStatementTest {
 	@Test public void executeShouldThrowExceptionOnUpdateOnClosedStatement() throws SQLException {
 		expectedEx.expect(SQLException.class);
 
-		PreparedStatement statement = BoltNeo4jPreparedStatement.newInstance(false, mockConnectionOpen(), StatementData.STATEMENT_CREATE);
+		PreparedStatement statement = BoltNeo4jPreparedStatement.newInstance(false, mockOpenConnection(), StatementData.STATEMENT_CREATE);
 		statement.close();
 
 		statement.execute();
@@ -740,7 +715,6 @@ public class BoltNeo4jPreparedStatementTest {
 
 		PreparedStatement statement = BoltNeo4jPreparedStatement.newInstance(false, mockConnectionClosed(), "", 0, 0, 0);
 		when(statement.executeQuery()).thenCallRealMethod();
-		Whitebox.setInternalState(statement, "statement", StatementData.STATEMENT_MATCH_ALL);
 		statement.execute();
 	}
 
@@ -749,7 +723,6 @@ public class BoltNeo4jPreparedStatementTest {
 
 		PreparedStatement statement = BoltNeo4jPreparedStatement.newInstance(false, mockConnectionClosed(), "", 0, 0, 0);
 		when(statement.executeUpdate()).thenCallRealMethod();
-		Whitebox.setInternalState(statement, "statement", StatementData.STATEMENT_CREATE);
 		statement.execute();
 	}
 
@@ -757,21 +730,16 @@ public class BoltNeo4jPreparedStatementTest {
 	/*        getUpdateCount        */
 	/*------------------------------*/
 	@Test public void getUpdateCountShouldReturnOne() throws SQLException {
-		BoltNeo4jPreparedStatement statement = mock(BoltNeo4jPreparedStatement.class);
-		when(statement.isClosed()).thenReturn(false);
-		when(statement.getUpdateCount()).thenCallRealMethod();
-		final Object o = null;
-		Whitebox.setInternalState(statement, "currentResultSet", o);
-		Whitebox.setInternalState(statement, "currentUpdateCount", 1);
+		Result result = mockResultWithUpdateCount(1);
+		BoltNeo4jPreparedStatement statement = new BoltNeo4jPreparedStatement(mockOpenConnectionWithResult(result), resultSetFactory, "RETURN 42");
+		statement.executeUpdate();
 
 		assertEquals(1, statement.getUpdateCount());
 	}
 
 	@Test public void getUpdateCountShouldReturnMinusOne() throws SQLException {
-		BoltNeo4jPreparedStatement statement = mock(BoltNeo4jPreparedStatement.class);
-		when(statement.isClosed()).thenReturn(false);
-		when(statement.getUpdateCount()).thenCallRealMethod();
-		Whitebox.setInternalState(statement, "currentResultSet", mock(BoltNeo4jResultSet.class));
+		ResultSetFactory nullRsFactory = (debug, stmt, iterator, params) -> null;
+		BoltNeo4jPreparedStatement statement = new BoltNeo4jPreparedStatement(mockOpenConnection(), nullRsFactory, "RETURN 42");
 
 		assertEquals(-1, statement.getUpdateCount());
 	}
@@ -779,7 +747,7 @@ public class BoltNeo4jPreparedStatementTest {
 	@Test public void getUpdateCountShouldThrowExceptionOnClosedStatement() throws SQLException {
 		expectedEx.expect(SQLException.class);
 
-		PreparedStatement statement = BoltNeo4jPreparedStatement.newInstance(false, mockConnectionOpen(), StatementData.STATEMENT_MATCH_ALL);
+		PreparedStatement statement = BoltNeo4jPreparedStatement.newInstance(false, mockOpenConnection(), StatementData.STATEMENT_MATCH_ALL);
 		statement.close();
 
 		statement.getUpdateCount();
@@ -789,28 +757,25 @@ public class BoltNeo4jPreparedStatementTest {
 	/*         getResultSet         */
 	/*------------------------------*/
 	@Test public void getResultSetShouldNotReturnNull() throws SQLException {
-		BoltNeo4jStatement statement = mock(BoltNeo4jStatement.class);
-		when(statement.isClosed()).thenReturn(false);
-		when(statement.getResultSet()).thenCallRealMethod();
-		Whitebox.setInternalState(statement, "currentResultSet", mock(BoltNeo4jResultSet.class));
-		Whitebox.setInternalState(statement, "currentUpdateCount", -1);
+		Result result = mock(Result.class, RETURNS_DEEP_STUBS);
+		BoltNeo4jPreparedStatement statement = new BoltNeo4jPreparedStatement(mockOpenConnectionWithResult(result), resultSetFactory, "RETURN 42");
+		statement.executeQuery();
 
-		assertTrue(statement.getResultSet() != null);
+		assertNotNull(statement.getResultSet());
 	}
 
 	@Test public void getResultSetShouldReturnNull() throws SQLException {
 		BoltNeo4jStatement statement = mock(BoltNeo4jStatement.class);
 		when(statement.isClosed()).thenReturn(false);
 		when(statement.getResultSet()).thenCallRealMethod();
-		Whitebox.setInternalState(statement, "currentUpdateCount", 1);
 
-		assertEquals(null, statement.getResultSet());
+		assertNull(statement.getResultSet());
 	}
 
 	@Test public void getResultSetShouldThrowExceptionOnClosedStatement() throws SQLException {
 		expectedEx.expect(SQLException.class);
 
-		PreparedStatement statement = BoltNeo4jPreparedStatement.newInstance(false, mockConnectionOpen(), StatementData.STATEMENT_MATCH_ALL);
+		PreparedStatement statement = BoltNeo4jPreparedStatement.newInstance(false, mockOpenConnection(), StatementData.STATEMENT_MATCH_ALL);
 		statement.close();
 
 		statement.getResultSet();
@@ -821,15 +786,7 @@ public class BoltNeo4jPreparedStatementTest {
 	/*------------------------------*/
 
 	@Test public void addBatchShouldAddParametersToStack() throws SQLException {
-		PreparedStatement stmt = mock(BoltNeo4jPreparedStatement.class, CALLS_REAL_METHODS);
-		Whitebox.setInternalState(stmt, "batchStatements", new ArrayList<>());
-		String statementString = "MATCH n WHERE id(n) = ? SET n.property=1";
-		String replacedStatementString = PreparedStatementBuilder.replacePlaceholders(statementString);
-		Whitebox.setInternalState(stmt, "statement", replacedStatementString);
-		Whitebox.setInternalState(stmt, "connection", mockConnectionOpenWithTransactionThatReturns(null));
-		Whitebox.setInternalState(stmt, "parametersNumber", PreparedStatementBuilder.namedParameterCount(replacedStatementString));
-		Whitebox.setInternalState(stmt, "parameters", new HashMap<>());
-		Whitebox.setInternalState(stmt, "batchParameters", new ArrayList<>());
+		BoltNeo4jPreparedStatement stmt = new BoltNeo4jPreparedStatement(mockOpenConnection(), resultSetFactory, "RETURN $1");
 
 		stmt.setInt(1, 1);
 		stmt.addBatch();
@@ -844,30 +801,22 @@ public class BoltNeo4jPreparedStatementTest {
 			{
 				this.put("1", 2);
 			}
-		}), Whitebox.getInternalState(stmt, "batchParameters"));
+		}), stmt.getBatchParameters());
 	}
 
 	@Test public void addBatchShouldClearParameters() throws SQLException {
-		PreparedStatement stmt = mock(BoltNeo4jPreparedStatement.class, CALLS_REAL_METHODS);
-		Whitebox.setInternalState(stmt, "batchStatements", new ArrayList<>());
-		String statementString = "MATCH n WHERE id(n) = ? SET n.property=1";
-		String replacedStatementString = PreparedStatementBuilder.replacePlaceholders(statementString);
-		Whitebox.setInternalState(stmt, "statement", replacedStatementString);
-		Whitebox.setInternalState(stmt, "connection", mockConnectionOpenWithTransactionThatReturns(null));
-		Whitebox.setInternalState(stmt, "parametersNumber", PreparedStatementBuilder.namedParameterCount(replacedStatementString));
-		Whitebox.setInternalState(stmt, "parameters", new HashMap<>());
-		Whitebox.setInternalState(stmt, "batchParameters", new ArrayList<>());
-
+		BoltNeo4jPreparedStatement stmt = new BoltNeo4jPreparedStatement(mockOpenConnection(), resultSetFactory, "RETURN $1");
 		stmt.setInt(1, 1);
+
 		stmt.addBatch();
 
-		assertEquals(Collections.EMPTY_MAP, Whitebox.getInternalState(stmt, "parameters"));
+		assertEquals(Collections.EMPTY_MAP, stmt.getParameters());
 	}
 
 	@Test public void addBatchShouldThrowExceptionIfClosedStatement() throws SQLException {
 		expectedEx.expect(SQLException.class);
 
-		PreparedStatement stmt = BoltNeo4jPreparedStatement.newInstance(false, Mocker.mockConnectionOpen(), "?");
+		PreparedStatement stmt = BoltNeo4jPreparedStatement.newInstance(false, Mocker.mockOpenConnection(), "?");
 		stmt.setInt(1, 1);
 		stmt.close();
 		stmt.addBatch();
@@ -878,26 +827,18 @@ public class BoltNeo4jPreparedStatementTest {
 	/*------------------------------*/
 
 	@Test public void clearBatchShouldWork() throws SQLException {
-		PreparedStatement stmt = mock(BoltNeo4jPreparedStatement.class, CALLS_REAL_METHODS);
-		Whitebox.setInternalState(stmt, "batchStatements", new ArrayList<>());
-		String statementString = "?";
-		String replacedStatementString = PreparedStatementBuilder.replacePlaceholders(statementString);
-		Whitebox.setInternalState(stmt, "statement", replacedStatementString);
-		Whitebox.setInternalState(stmt, "connection", mockConnectionOpenWithTransactionThatReturns(null));
-		Whitebox.setInternalState(stmt, "parametersNumber", PreparedStatementBuilder.namedParameterCount(replacedStatementString));
-		Whitebox.setInternalState(stmt, "parameters", new HashMap<>());
-		Whitebox.setInternalState(stmt, "batchParameters", new ArrayList<>());
-
+		BoltNeo4jPreparedStatement stmt = new BoltNeo4jPreparedStatement(mockOpenConnection(), resultSetFactory, "RETURN $1");
 		stmt.setInt(1, 1);
+
 		stmt.clearBatch();
 
-		assertEquals(Collections.EMPTY_LIST, Whitebox.getInternalState(stmt, "batchParameters"));
+		assertEquals(Collections.EMPTY_LIST, stmt.getBatchParameters());
 	}
 
 	@Test public void clearBatchShouldThrowExceptionIfClosedStatement() throws SQLException {
 		expectedEx.expect(SQLException.class);
 
-		PreparedStatement stmt = BoltNeo4jPreparedStatement.newInstance(false, Mocker.mockConnectionOpen(), "?");
+		PreparedStatement stmt = BoltNeo4jPreparedStatement.newInstance(false, Mocker.mockOpenConnection(), "?");
 		stmt.close();
 		stmt.clearBatch();
 	}
@@ -908,7 +849,7 @@ public class BoltNeo4jPreparedStatementTest {
 
 	@Test public void executeBatchShouldWork() throws SQLException {
 		Transaction transaction = mock(Transaction.class);
-		BoltNeo4jConnectionImpl connection = mockConnectionOpen();
+		BoltNeo4jConnectionImpl connection = mockOpenConnection();
 		when(connection.getTransaction()).thenReturn(transaction);
         when(connection.getAutoCommit()).thenReturn(true);
 
@@ -932,7 +873,7 @@ public class BoltNeo4jPreparedStatementTest {
 	}
 
 	@Test public void executeBatchShouldThrowExceptionOnError() throws SQLException {
-		PreparedStatement stmt = BoltNeo4jPreparedStatement.newInstance(false, Mocker.mockConnectionOpen(), "?");
+		PreparedStatement stmt = BoltNeo4jPreparedStatement.newInstance(false, Mocker.mockOpenConnection(), "?");
 		stmt.setInt(1, 1);
 		stmt.addBatch();
 		stmt.setInt(1, 2);
@@ -973,10 +914,10 @@ public class BoltNeo4jPreparedStatementTest {
 	/*------------------------------*/
 
 	@Test public void getConnectionShouldWork() throws SQLException {
-		PreparedStatement stmt = BoltNeo4jPreparedStatement.newInstance(false, Mocker.mockConnectionOpen(), "?");
+		PreparedStatement stmt = BoltNeo4jPreparedStatement.newInstance(false, Mocker.mockOpenConnection(), "?");
 
 		assertNotNull(stmt.getConnection());
-		assertEquals(Mocker.mockConnectionOpen().getClass(), stmt.getConnection().getClass());
+		assertEquals(Mocker.mockOpenConnection().getClass(), stmt.getConnection().getClass());
 	}
 
 	@Test public void getConnectionShouldThrowExceptionOnClosedStatement() throws SQLException {
@@ -995,7 +936,7 @@ public class BoltNeo4jPreparedStatementTest {
 	@Test public void setArrayShouldInsertTheCorrectArray() throws SQLException {
 		ListArray array = new ListArray(Arrays.asList(1L,2L,4L), INTEGER);
 		this.preparedStatementOneParam.setArray(1, array);
-		HashMap<String, Object> value = Whitebox.getInternalState(this.preparedStatementOneParam, "parameters");
-		assertArrayEquals(new Long[]{1L,2L,4L}, (Long[]) value.get("1"));
+
+		assertArrayEquals(new Long[]{1L,2L,4L}, (Long[]) preparedStatementOneParam.getParameters().get("1"));
 	}
 }
diff --git a/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/BoltNeo4jResultSetGettersTest.java b/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/BoltNeo4jResultSetGettersTest.java
index 0afbecf0..f292bc3b 100644
--- a/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/BoltNeo4jResultSetGettersTest.java
+++ b/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/BoltNeo4jResultSetGettersTest.java
@@ -23,19 +23,23 @@ import org.junit.BeforeClass;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.mockito.Mockito;
 import org.neo4j.driver.Result;
+import org.neo4j.driver.Value;
+import org.neo4j.driver.Values;
 import org.neo4j.jdbc.Neo4jConnection;
 import org.neo4j.jdbc.Neo4jResultSet;
 import org.neo4j.jdbc.Neo4jStatement;
 import org.neo4j.jdbc.bolt.data.ResultSetData;
-import org.powermock.reflect.Whitebox;
 
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.sql.Statement;
 import java.util.*;
 
 import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.neo4j.jdbc.bolt.utils.Mocker.mockResultWithValues;
 
 /**
  * @author AgileLARUS
@@ -176,10 +180,10 @@ public class BoltNeo4jResultSetGettersTest {
 	@Test public void getStringByLabelShouldReturnCorrectVirtualColumn() throws SQLException {
 		Result statementResult = ResultSetData
 				.buildResultCursor(ResultSetData.KEYS_RECORD_LIST_MORE_ELEMENTS_NODES, ResultSetData.RECORD_LIST_MORE_ELEMENTS_NODES);
-		Neo4jConnection c = Mockito.mock(Neo4jConnection.class);
-		Mockito.when(c.getFlattening()).thenReturn(1);
-		Neo4jStatement stmt = Mockito.mock(Neo4jStatement.class);
-		Mockito.when(stmt.getConnection()).thenReturn(c);
+		Neo4jConnection c = mock(Neo4jConnection.class);
+		when(c.getFlattening()).thenReturn(1);
+		Neo4jStatement stmt = mock(Neo4jStatement.class);
+		when(stmt.getConnection()).thenReturn(c);
 		ResultSet resultSet = BoltNeo4jResultSet.newInstance(false, stmt, statementResult);
 
 		resultSet.next();
@@ -189,10 +193,10 @@ public class BoltNeo4jResultSetGettersTest {
 	@Test public void getStringByIndexShouldReturnCorrectVirtualColumn() throws SQLException {
 		Result statementResult = ResultSetData
 				.buildResultCursor(ResultSetData.KEYS_RECORD_LIST_MORE_ELEMENTS_NODES, ResultSetData.RECORD_LIST_MORE_ELEMENTS_NODES);
-		Neo4jConnection c = Mockito.mock(Neo4jConnection.class);
-		Mockito.when(c.getFlattening()).thenReturn(1);
-		Neo4jStatement stmt = Mockito.mock(Neo4jStatement.class);
-		Mockito.when(stmt.getConnection()).thenReturn(c);
+		Neo4jConnection c = mock(Neo4jConnection.class);
+		when(c.getFlattening()).thenReturn(1);
+		Neo4jStatement stmt = mock(Neo4jStatement.class);
+		when(stmt.getConnection()).thenReturn(c);
 		ResultSet resultSet = BoltNeo4jResultSet.newInstance(false, stmt, statementResult);
 
 		resultSet.next();
@@ -335,10 +339,10 @@ public class BoltNeo4jResultSetGettersTest {
 	@Test public void getIntByLabelShouldReturnCorrectVirtualColumn() throws SQLException {
 		Result statementResult = ResultSetData
 				.buildResultCursor(ResultSetData.KEYS_RECORD_LIST_MORE_ELEMENTS_NODES, ResultSetData.RECORD_LIST_MORE_ELEMENTS_NODES);
-		Neo4jConnection c = Mockito.mock(Neo4jConnection.class);
-		Mockito.when(c.getFlattening()).thenReturn(1);
-		Neo4jStatement stmt = Mockito.mock(Neo4jStatement.class);
-		Mockito.when(stmt.getConnection()).thenReturn(c);
+		Neo4jConnection c = mock(Neo4jConnection.class);
+		when(c.getFlattening()).thenReturn(1);
+		Neo4jStatement stmt = mock(Neo4jStatement.class);
+		when(stmt.getConnection()).thenReturn(c);
 		ResultSet resultSet = BoltNeo4jResultSet.newInstance(false, stmt, statementResult);
 
 		resultSet.next();
@@ -349,10 +353,10 @@ public class BoltNeo4jResultSetGettersTest {
 	@Test public void getIntByIndexShouldReturnCorrectVirtualColumn() throws SQLException {
 		Result statementResult = ResultSetData
 				.buildResultCursor(ResultSetData.KEYS_RECORD_LIST_MORE_ELEMENTS_NODES, ResultSetData.RECORD_LIST_MORE_ELEMENTS_NODES);
-		Neo4jConnection c = Mockito.mock(Neo4jConnection.class);
-		Mockito.when(c.getFlattening()).thenReturn(1);
-		Neo4jStatement stmt = Mockito.mock(Neo4jStatement.class);
-		Mockito.when(stmt.getConnection()).thenReturn(c);
+		Neo4jConnection c = mock(Neo4jConnection.class);
+		when(c.getFlattening()).thenReturn(1);
+		Neo4jStatement stmt = mock(Neo4jStatement.class);
+		when(stmt.getConnection()).thenReturn(c);
 		ResultSet resultSet = BoltNeo4jResultSet.newInstance(false, stmt, statementResult);
 
 		resultSet.next();
@@ -1399,10 +1403,10 @@ public class BoltNeo4jResultSetGettersTest {
 	@Test public void getArrayByLabelShouldReturnCorrectVirtualColumn() throws SQLException {
 		Result statementResult = ResultSetData
 				.buildResultCursor(ResultSetData.KEYS_RECORD_LIST_MORE_ELEMENTS_NODES, ResultSetData.RECORD_LIST_MORE_ELEMENTS_NODES);
-		Neo4jConnection c = Mockito.mock(Neo4jConnection.class);
-		Mockito.when(c.getFlattening()).thenReturn(1);
-		Neo4jStatement stmt = Mockito.mock(Neo4jStatement.class);
-		Mockito.when(stmt.getConnection()).thenReturn(c);
+		Neo4jConnection c = mock(Neo4jConnection.class);
+		when(c.getFlattening()).thenReturn(1);
+		Neo4jStatement stmt = mock(Neo4jStatement.class);
+		when(stmt.getConnection()).thenReturn(c);
 		ResultSet resultSet = BoltNeo4jResultSet.newInstance(false, stmt, statementResult);
 
 		resultSet.next();
@@ -1412,10 +1416,10 @@ public class BoltNeo4jResultSetGettersTest {
 	@Test public void getArrayByIndexShouldReturnCorrectVirtualColumn() throws SQLException {
 		Result statementResult = ResultSetData
 				.buildResultCursor(ResultSetData.KEYS_RECORD_LIST_MORE_ELEMENTS_NODES, ResultSetData.RECORD_LIST_MORE_ELEMENTS_NODES);
-		Neo4jConnection c = Mockito.mock(Neo4jConnection.class);
-		Mockito.when(c.getFlattening()).thenReturn(1);
-		Neo4jStatement stmt = Mockito.mock(Neo4jStatement.class);
-		Mockito.when(stmt.getConnection()).thenReturn(c);
+		Neo4jConnection c = mock(Neo4jConnection.class);
+		when(c.getFlattening()).thenReturn(1);
+		Neo4jStatement stmt = mock(Neo4jStatement.class);
+		when(stmt.getConnection()).thenReturn(c);
 		ResultSet resultSet = BoltNeo4jResultSet.newInstance(false, stmt, statementResult);
 
 		resultSet.next();
@@ -1436,15 +1440,42 @@ public class BoltNeo4jResultSetGettersTest {
 		resultSet.wasNull();
 	}
 
-	@Test public void wasNullShouldReturnFalse() throws SQLException {
-		ResultSet resultSet = Mockito.mock(BoltNeo4jResultSet.class);
-		Whitebox.setInternalState(resultSet, "wasNull", false);
-		resultSet.wasNull();
+	@Test public void wasNullIfIterationNotStarted() throws SQLException {
+		ResultSet resultSet = new BoltNeo4jResultSet(mock(Statement.class), mock(Result.class));
+
+		boolean wasNull = resultSet.wasNull();
+
+		assertFalse(wasNull);
 	}
 
-	@Test public void wasNullShouldReturnTrue() throws SQLException {
-		ResultSet resultSet = Mockito.mock(BoltNeo4jResultSet.class);
-		Whitebox.setInternalState(resultSet, "wasNull", true);
-		resultSet.wasNull();
+	@Test public void wasNullIfLastColumnNotNull() throws SQLException {
+		Result result = mockResultWithValues(values("COLUMN", Values.value(42)));
+		ResultSet resultSet = new BoltNeo4jResultSet(mock(Statement.class), result);
+		resultSet.next();
+		int column = resultSet.getInt("COLUMN");
+
+		boolean wasNull = resultSet.wasNull();
+
+		assertEquals(42, column);
+		assertFalse(wasNull);
 	}
+
+	@Test public void wasNullIfLastColumnWasNull() throws SQLException {
+		Result result = mockResultWithValues(values("COLUMN", Values.NULL));
+		ResultSet resultSet = new BoltNeo4jResultSet(mock(Statement.class), result);
+		resultSet.next();
+		String column = resultSet.getString("COLUMN");
+
+		boolean wasNull = resultSet.wasNull();
+
+		assertNull(column);
+		assertTrue(wasNull);
+	}
+
+	private LinkedHashMap<String, Value> values(String name, Value value) {
+		LinkedHashMap<String, Value> values = new LinkedHashMap<>();
+		values.put(name, value);
+		return values;
+	}
+
 }
diff --git a/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/BoltNeo4jStatementTest.java b/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/BoltNeo4jStatementTest.java
index d9ea5190..7971c617 100644
--- a/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/BoltNeo4jStatementTest.java
+++ b/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/BoltNeo4jStatementTest.java
@@ -24,33 +24,23 @@ import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.junit.runner.RunWith;
 import org.mockito.Mockito;
 import org.neo4j.driver.Result;
 import org.neo4j.driver.Session;
 import org.neo4j.driver.Transaction;
 import org.neo4j.driver.summary.ResultSummary;
 import org.neo4j.driver.summary.SummaryCounters;
-import org.neo4j.jdbc.Neo4jStatement;
 import org.neo4j.jdbc.bolt.data.StatementData;
 import org.neo4j.jdbc.bolt.impl.BoltNeo4jConnectionImpl;
 import org.neo4j.jdbc.bolt.utils.Mocker;
 import org.neo4j.jdbc.bolt.utils.ReflectionUtil;
-import org.neo4j.jdbc.utils.BoltNeo4jUtils;
-import org.neo4j.jdbc.utils.Neo4jInvocationHandler;
-import org.powermock.api.mockito.PowerMockito;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-import org.powermock.reflect.Whitebox;
-
-import java.lang.reflect.Proxy;
+
 import java.sql.BatchUpdateException;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Properties;
@@ -60,11 +50,10 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyBoolean;
 import static org.mockito.Mockito.anyMap;
 import static org.mockito.Mockito.doCallRealMethod;
 import static org.mockito.Mockito.doNothing;
@@ -74,49 +63,47 @@ import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 import static org.neo4j.jdbc.bolt.utils.Mocker.mockConnectionClosed;
-import static org.neo4j.jdbc.bolt.utils.Mocker.mockConnectionOpen;
-import static org.neo4j.jdbc.bolt.utils.Mocker.mockConnectionOpenWithTransactionThatReturns;
+import static org.neo4j.jdbc.bolt.utils.Mocker.mockOpenConnection;
+import static org.neo4j.jdbc.bolt.utils.Mocker.mockOpenConnectionWithResult;
 import static org.neo4j.jdbc.bolt.utils.Mocker.mockDriverOpen;
-import static org.powermock.api.mockito.PowerMockito.mockStatic;
-import static org.powermock.api.mockito.PowerMockito.verifyStatic;
+import static org.neo4j.jdbc.bolt.utils.Mocker.mockResultWithUpdateCount;
 
 /**
  * @author AgileLARUS
  * @since 3.0.0
  */
-@RunWith(PowerMockRunner.class)
-@PrepareForTest({ BoltNeo4jStatement.class, BoltNeo4jResultSet.class, Session.class, BoltNeo4jUtils.class })
-
 public class BoltNeo4jStatementTest {
 
 	@Rule
 	public ExpectedException expectedEx = ExpectedException.none();
+	private BoltNeo4jResultSet expectedResultSet;
+	private ResultSetFactory resultSetFactory;
 
 	@Before public void interceptBoltResultSetConstructor() throws Exception {
+		expectedResultSet = mock(BoltNeo4jResultSet.class);
+		resultSetFactory = (debug, statement, iterator, params) -> expectedResultSet;
 		BoltNeo4jResultSet mockedRS = mock(BoltNeo4jResultSet.class);
 		doNothing().when(mockedRS).close();
-		mockStatic(BoltNeo4jResultSet.class);
-		PowerMockito.when(BoltNeo4jResultSet.newInstance(anyBoolean(), any(Neo4jStatement.class), any(Result.class))).thenReturn(mockedRS);
 	}
 
 	/*------------------------------*/
 	/*             close            */
 	/*------------------------------*/
 	@Test public void closeShouldCloseExistingResultSet() throws Exception {
-		Result mockedSR = mock(Result.class);
-		Statement statement = BoltNeo4jStatement.newInstance(false, mockConnectionOpenWithTransactionThatReturns(mockedSR));
+		Result result = mock(Result.class);
+		Statement statement = new BoltNeo4jStatement(mockOpenConnectionWithResult(result), resultSetFactory);
 		final ResultSet resultSet = statement.executeQuery(StatementData.STATEMENT_MATCH_ALL);
 		statement.close();
 
-		verify(resultSet, times(1)).close();
-
+		assertSame(expectedResultSet, resultSet);
+		verify(expectedResultSet, times(1)).close();
 	}
 
 	@Test public void closeMultipleTimesIsNOOP() throws Exception {
-		Result mockedSR = mock(Result.class);
-
-		Statement statement = BoltNeo4jStatement.newInstance(false, mockConnectionOpenWithTransactionThatReturns(mockedSR));
+		Result mockedResult = mock(Result.class);
+		Statement statement = new BoltNeo4jStatement(mockOpenConnectionWithResult(mockedResult), resultSetFactory);
 		final ResultSet resultSet = statement.executeQuery(StatementData.STATEMENT_MATCH_ALL);
+
 		statement.close();
 		statement.close();
 		statement.close();
@@ -128,7 +115,7 @@ public class BoltNeo4jStatementTest {
 
 		Transaction mockTransaction = mock(Transaction.class);
 
-		BoltNeo4jConnectionImpl mockConnection = mockConnectionOpen();
+		BoltNeo4jConnectionImpl mockConnection = mockOpenConnection();
 		when(mockConnection.getTransaction()).thenReturn(mockTransaction);
 
 		Statement statement = BoltNeo4jStatement.newInstance(false, mockConnection);
@@ -145,7 +132,7 @@ public class BoltNeo4jStatementTest {
 	/*------------------------------*/
 
 	@Test public void isClosedShouldReturnFalseWhenCreated() throws SQLException {
-		Statement statement = BoltNeo4jStatement.newInstance(false, mockConnectionOpen());
+		Statement statement = BoltNeo4jStatement.newInstance(false, mockOpenConnection());
 		assertFalse(statement.isClosed());
 	}
 
@@ -157,7 +144,7 @@ public class BoltNeo4jStatementTest {
 		Result mockResult = mock(Result.class);
 
 		Statement statement = BoltNeo4jStatement
-				.newInstance(false, mockConnectionOpenWithTransactionThatReturns(mockResult), ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
+				.newInstance(false, mockOpenConnectionWithResult(mockResult), ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
 						ResultSet.HOLD_CURSORS_OVER_COMMIT);
 		statement.executeQuery(StatementData.STATEMENT_CREATE);
 	}
@@ -170,20 +157,20 @@ public class BoltNeo4jStatementTest {
 	}
 
 	@Test public void executeQueryShouldReturnCorrectResultSetStructureConnectionNotAutocommit() throws Exception {
-		BoltNeo4jConnectionImpl mockConnection = mockConnectionOpenWithTransactionThatReturns(null);
+		BoltNeo4jConnectionImpl mockConnection = mockOpenConnectionWithResult(null);
 
 		Statement statement = BoltNeo4jStatement
 				.newInstance(false, mockConnection, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT);
 		statement.executeQuery(StatementData.STATEMENT_MATCH_ALL);
 
-		verifyStatic(BoltNeo4jResultSet.class);
+//		verifyStatic(BoltNeo4jResultSet.class);
 		BoltNeo4jResultSet.newInstance(false, statement, null, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT);
 	}
 
 	@Test public void executeQueryShouldThrowExceptionOnClosedStatement() throws SQLException {
 		expectedEx.expect(SQLException.class);
 
-		Statement statement = BoltNeo4jStatement.newInstance(false, mockConnectionOpen());
+		Statement statement = BoltNeo4jStatement.newInstance(false, mockOpenConnection());
 		statement.close();
 
 		statement.executeQuery(StatementData.STATEMENT_MATCH_ALL);
@@ -230,7 +217,7 @@ public class BoltNeo4jStatementTest {
 		when(mockSummaryCounters.nodesDeleted()).thenReturn(0);
 
 		Statement statement = BoltNeo4jStatement
-				.newInstance(false, mockConnectionOpenWithTransactionThatReturns(mockResult), ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
+				.newInstance(false, mockOpenConnectionWithResult(mockResult), ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
 						ResultSet.HOLD_CURSORS_OVER_COMMIT);
 		statement.executeUpdate(StatementData.STATEMENT_CREATE);
 	}
@@ -307,13 +294,10 @@ public class BoltNeo4jStatementTest {
 	/*            execute           */
 	/*------------------------------*/
 	@Test public void executeShouldRunQuery() throws SQLException {
-		Result mockResult = mock(Result.class);
-
-		final BoltNeo4jConnectionImpl mockedConnection = mockConnectionOpenWithTransactionThatReturns(mockResult);
-		mockStatic(BoltNeo4jUtils.class, invocationOnMock -> invocationOnMock.getMethod().getName().equals("hasResult"));
-		Statement statement = BoltNeo4jStatement
-				.newInstance(false, mockedConnection, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
-						ResultSet.HOLD_CURSORS_OVER_COMMIT);
+		Statement statement = new BoltNeo4jStatement(
+				mockOpenConnectionWithResult(mockResultWithUpdateCount(1)),
+				resultSetFactory,
+				ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT);
 		statement.execute(StatementData.STATEMENT_MATCH_ALL);
 	}
 
@@ -328,7 +312,7 @@ public class BoltNeo4jStatementTest {
 		when(mockSummaryCounters.nodesDeleted()).thenReturn(0);
 
 		Statement statement = BoltNeo4jStatement
-				.newInstance(false, mockConnectionOpenWithTransactionThatReturns(mockResult), ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
+				.newInstance(false, mockOpenConnectionWithResult(mockResult), ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
 						ResultSet.HOLD_CURSORS_OVER_COMMIT);
 		statement.execute(StatementData.STATEMENT_CREATE);
 	}
@@ -350,7 +334,7 @@ public class BoltNeo4jStatementTest {
 	@Test public void executeShouldThrowExceptionOnQueryOnClosedStatement() throws SQLException {
 		expectedEx.expect(SQLException.class);
 
-		Statement statement = BoltNeo4jStatement.newInstance(false, mockConnectionOpen());
+		Statement statement = BoltNeo4jStatement.newInstance(false, mockOpenConnection());
 		statement.close();
 
 		statement.execute(StatementData.STATEMENT_MATCH_ALL);
@@ -359,7 +343,7 @@ public class BoltNeo4jStatementTest {
 	@Test public void executeShouldThrowExceptionOnUpdateOnClosedStatement() throws SQLException {
 		expectedEx.expect(SQLException.class);
 
-		Statement statement = BoltNeo4jStatement.newInstance(false, mockConnectionOpen());
+		Statement statement = BoltNeo4jStatement.newInstance(false, mockOpenConnection());
 		statement.close();
 
 		statement.execute(StatementData.STATEMENT_CREATE);
@@ -404,21 +388,17 @@ public class BoltNeo4jStatementTest {
 	/*        getUpdateCount        */
 	/*------------------------------*/
 	@Test public void getUpdateCountShouldReturnOne() throws SQLException {
-		BoltNeo4jStatement statement = mock(BoltNeo4jStatement.class);
-		when(statement.isClosed()).thenReturn(false);
-		when(statement.getUpdateCount()).thenCallRealMethod();
-		Object nullValue = null;
-		Whitebox.setInternalState(statement, "currentResultSet", nullValue);
-		Whitebox.setInternalState(statement, "currentUpdateCount", 1);
+		BoltNeo4jStatement statement = new BoltNeo4jStatement(
+				mockOpenConnectionWithResult(mockResultWithUpdateCount(1)),
+				resultSetFactory
+		);
+		statement.execute("RETURN 42");
 
 		assertEquals(1, statement.getUpdateCount());
 	}
 
 	@Test public void getUpdateCountShouldReturnMinusOne() throws SQLException {
-		BoltNeo4jStatement statement = mock(BoltNeo4jStatement.class);
-		when(statement.isClosed()).thenReturn(false);
-		when(statement.getUpdateCount()).thenCallRealMethod();
-		Whitebox.setInternalState(statement, "currentResultSet", mock(BoltNeo4jResultSet.class));
+		BoltNeo4jStatement statement = new BoltNeo4jStatement(mockOpenConnection(), resultSetFactory);
 
 		assertEquals(-1, statement.getUpdateCount());
 	}
@@ -426,7 +406,7 @@ public class BoltNeo4jStatementTest {
 	@Test public void getUpdateCountShouldThrowExceptionOnClosedStatement() throws SQLException {
 		expectedEx.expect(SQLException.class);
 
-		Statement statement = BoltNeo4jStatement.newInstance(false, mockConnectionOpen());
+		Statement statement = BoltNeo4jStatement.newInstance(false, mockOpenConnection());
 		statement.close();
 
 		statement.getUpdateCount();
@@ -436,20 +416,18 @@ public class BoltNeo4jStatementTest {
 	/*         getResultSet         */
 	/*------------------------------*/
 	@Test public void getResultSetShouldNotReturnNull() throws SQLException {
-		BoltNeo4jStatement statement = mock(BoltNeo4jStatement.class);
-		when(statement.isClosed()).thenReturn(false);
-		when(statement.getResultSet()).thenCallRealMethod();
-		Whitebox.setInternalState(statement, "currentResultSet", mock(BoltNeo4jResultSet.class));
-		Whitebox.setInternalState(statement, "currentUpdateCount", -1);
+		Result result = mock(Result.class);
+		BoltNeo4jStatement statement = new BoltNeo4jStatement(mockOpenConnectionWithResult(result), resultSetFactory);
+		statement.executeQuery("RETURN 42");
 
-		assertTrue(statement.getResultSet() != null);
+		assertNotNull(statement.getResultSet());
 	}
 
 	@Test public void getResultSetShouldReturnNull() throws SQLException {
 		BoltNeo4jStatement statement = mock(BoltNeo4jStatement.class);
 		when(statement.isClosed()).thenReturn(false);
 		when(statement.getResultSet()).thenCallRealMethod();
-		Whitebox.setInternalState(statement, "currentUpdateCount", 1);
+//		Whitebox.setInternalState(statement, "currentUpdateCount", 1);
 
 		assertEquals(null, statement.getResultSet());
 	}
@@ -457,7 +435,7 @@ public class BoltNeo4jStatementTest {
 	@Test public void getResultSetShouldThrowExceptionOnClosedStatement() throws SQLException {
 		expectedEx.expect(SQLException.class);
 
-		Statement statement = BoltNeo4jStatement.newInstance(false, mockConnectionOpen());
+		Statement statement = BoltNeo4jStatement.newInstance(false, mockOpenConnection());
 		statement.close();
 
 		statement.getResultSet();
@@ -469,24 +447,20 @@ public class BoltNeo4jStatementTest {
 	/*------------------------------*/
 
 	@Test public void addBatchShouldAddStringToStack() throws SQLException {
-		mockStatic(Proxy.class);
-		Statement s = mock(BoltNeo4jStatement.class);
-		doCallRealMethod().when(s).addBatch(anyString());
-		Whitebox.setInternalState(s, "batchStatements", new ArrayList<>());
-		PowerMockito.when(Proxy.newProxyInstance(any(ClassLoader.class), any(Class[].class), any(Neo4jInvocationHandler.class))).thenReturn(s);
+		BoltNeo4jStatement statement = new BoltNeo4jStatement(mockOpenConnection(), resultSetFactory);
 
-		String str1 = "MATCH n WHERE id(n) = 1 SET n.property=1";
-		String str2 = "MATCH n WHERE id(n) = 2 SET n.property=2";
-		s.addBatch(str1);
-		s.addBatch(str2);
+		statement.addBatch("MATCH n WHERE id(n) = 1 SET n.property=1");
+		statement.addBatch("MATCH n WHERE id(n) = 2 SET n.property=2");
 
-		assertEquals(Arrays.asList(str1, str2), Whitebox.getInternalState(s, "batchStatements"));
+		assertEquals(Arrays.asList(
+				"MATCH n WHERE id(n) = 1 SET n.property=1",
+				"MATCH n WHERE id(n) = 2 SET n.property=2"), statement.getBatchStatements());
 	}
 
 	@Test public void addBatchShouldThrowExceptionIfClosedStatement() throws SQLException {
 		expectedEx.expect(SQLException.class);
 
-		Statement stmt = BoltNeo4jStatement.newInstance(false, Mocker.mockConnectionOpen());
+		Statement stmt = BoltNeo4jStatement.newInstance(false, Mocker.mockOpenConnection());
 		stmt.close();
 		stmt.addBatch("");
 	}
@@ -496,24 +470,19 @@ public class BoltNeo4jStatementTest {
 	/*------------------------------*/
 
 	@Test public void clearBatchShouldWork() throws SQLException {
-		mockStatic(Proxy.class);
-		Statement s = mock(BoltNeo4jStatement.class);
-		doCallRealMethod().when(s).addBatch(anyString());
-		doCallRealMethod().when(s).clearBatch();
-		Whitebox.setInternalState(s, "batchStatements", new ArrayList<>());
-		PowerMockito.when(Proxy.newProxyInstance(any(ClassLoader.class), any(Class[].class), any(Neo4jInvocationHandler.class))).thenReturn(s);
+		BoltNeo4jStatement statement = mock(BoltNeo4jStatement.class);
+		statement.addBatch("MATCH n WHERE id(n) = 1 SET n.property=1");
+		statement.addBatch("MATCH n WHERE id(n) = 2 SET n.property=2");
 
-		s.addBatch("MATCH n WHERE id(n) = 1 SET n.property=1");
-		s.addBatch("MATCH n WHERE id(n) = 2 SET n.property=2");
-		s.clearBatch();
+		statement.clearBatch();
 
-		assertEquals(Collections.EMPTY_LIST, Whitebox.getInternalState(s, "batchStatements"));
+		assertEquals(Collections.EMPTY_LIST, statement.getBatchStatements());
 	}
 
 	@Test public void clearBatchShouldThrowExceptionIfClosedStatement() throws SQLException {
 		expectedEx.expect(SQLException.class);
 
-		Statement stmt = BoltNeo4jStatement.newInstance(false, Mocker.mockConnectionOpen());
+		Statement stmt = BoltNeo4jStatement.newInstance(false, Mocker.mockOpenConnection());
 		stmt.close();
 		stmt.clearBatch();
 	}
@@ -524,7 +493,7 @@ public class BoltNeo4jStatementTest {
 
 	@Test public void executeBatchShouldWork() throws SQLException {
 		Transaction transaction = mock(Transaction.class);
-		BoltNeo4jConnectionImpl connection = mockConnectionOpen();
+		BoltNeo4jConnectionImpl connection = mockOpenConnection();
 		when(connection.getTransaction()).thenReturn(transaction);
 		when(connection.getAutoCommit()).thenReturn(true);
 		Result stmtResult = mock(Result.class);
@@ -547,7 +516,7 @@ public class BoltNeo4jStatementTest {
 	}
 
 	@Test public void executeBatchShouldThrowExceptionOnError() throws SQLException {
-		Statement stmt = BoltNeo4jStatement.newInstance(false, Mocker.mockConnectionOpen());
+		Statement stmt = BoltNeo4jStatement.newInstance(false, Mocker.mockOpenConnection());
 		stmt.addBatch("MATCH n WHERE id(n) = 1 SET n.property=1");
 		stmt.addBatch("MATCH n WHERE id(n) = 2 SET n.property=2");
 
@@ -586,10 +555,10 @@ public class BoltNeo4jStatementTest {
 	/*------------------------------*/
 
 	@Test public void getConnectionShouldWork() throws SQLException {
-		Statement stmt = BoltNeo4jStatement.newInstance(false, Mocker.mockConnectionOpen());
+		Statement stmt = BoltNeo4jStatement.newInstance(false, Mocker.mockOpenConnection());
 
 		assertNotNull(stmt.getConnection());
-		assertEquals(Mocker.mockConnectionOpen().getClass(), stmt.getConnection().getClass());
+		assertEquals(Mocker.mockOpenConnection().getClass(), stmt.getConnection().getClass());
 	}
 
 	@Test public void getConnectionShouldThrowExceptionOnClosedStatement() throws SQLException {
diff --git a/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/FakeRecord.java b/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/FakeRecord.java
new file mode 100644
index 00000000..d95fc3fe
--- /dev/null
+++ b/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/FakeRecord.java
@@ -0,0 +1,180 @@
+/**
+ * Copyright (c) 2016 LARUS Business Automation [http://www.larus-ba.it]
+ * <p>
+ * This file is part of the "LARUS Integration Framework for Neo4j".
+ * <p>
+ * The "LARUS Integration Framework for Neo4j" is licensed under the Apache License, Version 2.0 (the "License"); you
+ * may not use this file except in compliance with the License. You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ * <p>
+ * Created on 06/09/2021
+ */
+package org.neo4j.jdbc.bolt;
+
+import org.neo4j.driver.Record;
+import org.neo4j.driver.Value;
+import org.neo4j.driver.types.Entity;
+import org.neo4j.driver.types.Node;
+import org.neo4j.driver.types.Path;
+import org.neo4j.driver.types.Relationship;
+import org.neo4j.driver.util.Pair;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+
+/**
+ * @author AgileLARUS
+ * @since 3.0.0
+ */
+public class FakeRecord implements Record {
+
+    private final Map<String, Value> values;
+
+    public FakeRecord(LinkedHashMap<String, Value> values) {
+        this.values = values;
+    }
+
+    @Override
+    public List<String> keys() {
+        return new ArrayList<>(values.keySet());
+    }
+
+    @Override
+    public List<Value> values() {
+        return new ArrayList<>(values.values());
+    }
+
+    @Override
+    public boolean containsKey(String key) {
+        return values.containsKey(key);
+    }
+
+    @Override
+    public int index(String key) {
+        return keys().indexOf(key);
+    }
+
+    @Override
+    public Value get(String key) {
+        return values.get(key);
+    }
+
+    @Override
+    public Value get(int index) {
+        return values().get(index);
+    }
+
+    @Override
+    public int size() {
+        return values.size();
+    }
+
+    @Override
+    public Map<String, Object> asMap() {
+        return null;
+    }
+
+    @Override
+    public <T> Map<String, T> asMap(Function<Value, T> mapper) {
+        return null;
+    }
+
+    @Override
+    public List<Pair<String, Value>> fields() {
+        return null;
+    }
+
+    @Override
+    public Value get(String key, Value defaultValue) {
+        return null;
+    }
+
+    @Override
+    public Object get(String key, Object defaultValue) {
+        return null;
+    }
+
+    @Override
+    public Number get(String key, Number defaultValue) {
+        return null;
+    }
+
+    @Override
+    public Entity get(String key, Entity defaultValue) {
+        return null;
+    }
+
+    @Override
+    public Node get(String key, Node defaultValue) {
+        return null;
+    }
+
+    @Override
+    public Path get(String key, Path defaultValue) {
+        return null;
+    }
+
+    @Override
+    public Relationship get(String key, Relationship defaultValue) {
+        return null;
+    }
+
+    @Override
+    public List<Object> get(String key, List<Object> defaultValue) {
+        return null;
+    }
+
+    @Override
+    public <T> List<T> get(String key, List<T> defaultValue, Function<Value, T> mapFunc) {
+        return null;
+    }
+
+    @Override
+    public Map<String, Object> get(String key, Map<String, Object> defaultValue) {
+        return null;
+    }
+
+    @Override
+    public <T> Map<String, T> get(String key, Map<String, T> defaultValue, Function<Value, T> mapFunc) {
+        return null;
+    }
+
+    @Override
+    public int get(String key, int defaultValue) {
+        return 0;
+    }
+
+    @Override
+    public long get(String key, long defaultValue) {
+        return 0;
+    }
+
+    @Override
+    public boolean get(String key, boolean defaultValue) {
+        return false;
+    }
+
+    @Override
+    public String get(String key, String defaultValue) {
+        return null;
+    }
+
+    @Override
+    public float get(String key, float defaultValue) {
+        return 0;
+    }
+
+    @Override
+    public double get(String key, double defaultValue) {
+        return 0;
+    }
+}
diff --git a/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/cache/BoltDriverCacheTest.java b/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/cache/BoltDriverCacheTest.java
index 6cb5598d..e08ddc44 100644
--- a/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/cache/BoltDriverCacheTest.java
+++ b/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/cache/BoltDriverCacheTest.java
@@ -1,6 +1,5 @@
 package org.neo4j.jdbc.bolt.cache;
 
-import org.junit.AfterClass;
 import org.junit.Test;
 import org.mockito.Mockito;
 import org.neo4j.driver.AccessMode;
@@ -11,8 +10,6 @@ import org.neo4j.driver.Driver;
 import org.neo4j.driver.Session;
 import org.neo4j.driver.SessionConfig;
 import org.neo4j.driver.internal.InternalBookmark;
-import org.neo4j.jdbc.bolt.BoltDriver;
-import org.neo4j.jdbc.boltrouting.BoltRoutingNeo4jDriver;
 
 import java.net.URI;
 import java.net.URISyntaxException;
@@ -41,12 +38,6 @@ public class BoltDriverCacheTest {
 
     Function<BoltDriverCacheKey, Driver> builder = (params -> Mockito.mock(Driver.class));
 
-    @AfterClass
-    public static void tearDown() {
-        BoltRoutingNeo4jDriver.clearCache();
-        BoltDriver.clearCache();
-    }
-
     @Test
     public void cacheShouldBeThreadSafe() throws ExecutionException, InterruptedException {
         List<URI> url = Arrays.asList(URI.create("bolt://localhost"));
diff --git a/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/utils/JdbcConnectionTestUtils.java b/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/utils/JdbcConnectionTestUtils.java
index 0c8c2cce..8858b896 100644
--- a/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/utils/JdbcConnectionTestUtils.java
+++ b/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/utils/JdbcConnectionTestUtils.java
@@ -130,9 +130,6 @@ public class JdbcConnectionTestUtils {
             }
         } catch (SQLException e) {
             e.printStackTrace();
-        } finally {
-            BoltRoutingNeo4jDriver.clearCache();
-            BoltDriver.clearCache();
         }
     }
 
diff --git a/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/utils/Mocker.java b/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/utils/Mocker.java
index a7a488a4..7204dd34 100644
--- a/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/utils/Mocker.java
+++ b/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/bolt/utils/Mocker.java
@@ -30,11 +30,15 @@ import org.neo4j.driver.internal.async.NetworkSession;
 import org.neo4j.driver.internal.handlers.pulln.FetchSizeUtil;
 import org.neo4j.driver.internal.logging.DevNullLogging;
 import org.neo4j.driver.internal.spi.ConnectionProvider;
+import org.neo4j.driver.summary.ResultSummary;
+import org.neo4j.driver.summary.SummaryCounters;
+import org.neo4j.jdbc.bolt.FakeRecord;
 import org.neo4j.jdbc.bolt.impl.BoltNeo4jConnectionImpl;
 
 import java.sql.ResultSet;
 import java.sql.SQLException;
-import java.util.HashMap;
+import java.util.Collections;
+import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
@@ -123,7 +127,7 @@ public class Mocker {
 		return session;
 	}
 
-	public static BoltNeo4jConnectionImpl mockConnectionOpen() throws SQLException {
+	public static BoltNeo4jConnectionImpl mockOpenConnection() throws SQLException {
 		BoltNeo4jConnectionImpl mockConnection = mock(BoltNeo4jConnectionImpl.class);
 		when(mockConnection.isClosed()).thenReturn(false);
 		return mockConnection;
@@ -135,12 +139,12 @@ public class Mocker {
 		return mockConnection;
 	}
 
-	public static BoltNeo4jConnectionImpl mockConnectionOpenWithTransactionThatReturns(Result cur) throws SQLException {
+	public static BoltNeo4jConnectionImpl mockOpenConnectionWithResult(Result cur) throws SQLException {
 		Transaction mockTransaction = mock(Transaction.class);
 		when(mockTransaction.run(anyString())).thenReturn(cur);
 		when(mockTransaction.run(anyString(), any(Map.class))).thenReturn(cur);
 
-		BoltNeo4jConnectionImpl mockConnection = mockConnectionOpen();
+		BoltNeo4jConnectionImpl mockConnection = mockOpenConnection();
 		when(mockConnection.getTransaction()).thenReturn(mockTransaction);
 		return mockConnection;
 	}
@@ -153,4 +157,20 @@ public class Mocker {
 		Mockito.when(mockedDriver.session()).thenReturn(new InternalSession(networkSession));
 		return mockedDriver;
 	}
+
+	public static Result mockResultWithUpdateCount(int count) {
+		Result result = mock(Result.class);
+		ResultSummary resultSummary = mock(ResultSummary.class);
+		SummaryCounters summaryCounters = mock(SummaryCounters.class);
+		when(summaryCounters.propertiesSet()).thenReturn(count);
+		when(resultSummary.counters()).thenReturn(summaryCounters);
+		when(result.consume()).thenReturn(resultSummary);
+		return result;
+	}
+
+	public static Result mockResultWithValues(LinkedHashMap<String, Value> values) {
+		Result result = mock(Result.class);
+		when(result.list()).thenReturn(Collections.singletonList(new FakeRecord(values)));
+		return result;
+	}
 }
diff --git a/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/boltrouting/BoltRoutingIT.java b/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/boltrouting/BoltRoutingIT.java
index 8763e400..1e6c90f2 100644
--- a/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/boltrouting/BoltRoutingIT.java
+++ b/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/boltrouting/BoltRoutingIT.java
@@ -18,12 +18,21 @@
  */
 package org.neo4j.jdbc.boltrouting;
 
-import org.junit.*;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.neo4j.TestcontainersCausalCluster;
-import org.neo4j.jdbc.bolt.BoltDriver;
 
-import java.sql.*;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
 import java.time.Duration;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -58,8 +67,6 @@ public class BoltRoutingIT {
         if (cluster != null) {
             cluster.close();
         }
-        BoltRoutingNeo4jDriver.clearCache();
-        BoltDriver.clearCache();
     }
 
     @Rule public ExpectedException expectedEx = ExpectedException.none();
diff --git a/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/boltrouting/BoltRoutingNeo4jDriverTest.java b/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/boltrouting/BoltRoutingNeo4jDriverTest.java
index 53c4c8de..9f44950f 100644
--- a/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/boltrouting/BoltRoutingNeo4jDriverTest.java
+++ b/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/boltrouting/BoltRoutingNeo4jDriverTest.java
@@ -21,38 +21,28 @@ package org.neo4j.jdbc.boltrouting;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.junit.runner.RunWith;
-import org.neo4j.driver.Config;
-import org.neo4j.driver.GraphDatabase;
 import org.neo4j.jdbc.Neo4jDriver;
-import org.powermock.core.classloader.annotations.PowerMockIgnore;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
 
 import java.sql.SQLException;
 
 import static junit.framework.TestCase.assertFalse;
-import static org.junit.Assert.*;
 
 /**
  * @author AgileLARUS
  * @since 3.3.1
  */
-@RunWith(PowerMockRunner.class)
-@PrepareForTest({GraphDatabase.class, Config.TrustStrategy.class})
-
 public class BoltRoutingNeo4jDriverTest {
 
 	@Rule public ExpectedException expectedEx = ExpectedException.none();
 
-	@Test public void shoulNotAcceptURL() throws NoSuchFieldException, IllegalAccessException, ClassNotFoundException, SQLException {
+	@Test public void shoulNotAcceptURL() throws SQLException {
 		Neo4jDriver driver = new BoltRoutingNeo4jDriver();
 		assertFalse(driver.acceptsURL("jdbc:neo4j:http://localhost:7687"));
 		assertFalse(driver.acceptsURL("jdbc:file://192.168.0.1:7687"));
 		assertFalse(driver.acceptsURL("bolt://localhost:7687"));
 	}
 
-	@Test public void shouldThrowException() throws NoSuchFieldException, IllegalAccessException, ClassNotFoundException, SQLException {
+	@Test public void shouldThrowException() throws SQLException {
 		expectedEx.expect(SQLException.class);
 
 		Neo4jDriver driver = new BoltRoutingNeo4jDriver();
diff --git a/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/boltrouting/BoltRoutingNeo4jDriverUrlTest.java b/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/boltrouting/BoltRoutingNeo4jDriverUrlTest.java
index 7a0a03e5..619a9863 100644
--- a/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/boltrouting/BoltRoutingNeo4jDriverUrlTest.java
+++ b/neo4j-jdbc-bolt/src/test/java/org/neo4j/jdbc/boltrouting/BoltRoutingNeo4jDriverUrlTest.java
@@ -32,10 +32,6 @@ import org.neo4j.driver.Config;
 import org.neo4j.driver.GraphDatabase;
 import org.neo4j.jdbc.Neo4jDriver;
 import org.neo4j.jdbc.bolt.utils.Mocker;
-import org.powermock.api.mockito.PowerMockito;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-import org.powermock.modules.junit4.PowerMockRunnerDelegate;
 
 import java.net.URI;
 import java.net.URISyntaxException;
@@ -51,9 +47,7 @@ import static org.mockito.Matchers.any;
  * @author AgileLARUS
  * @since 3.0.0
  */
-@RunWith(PowerMockRunner.class)
-@PrepareForTest({GraphDatabase.class, Config.TrustStrategy.class, AuthTokens.class})
-@PowerMockRunnerDelegate(Parameterized.class)
+@RunWith(Parameterized.class)
 public class BoltRoutingNeo4jDriverUrlTest {
 
 	@Rule public ExpectedException expectedEx = ExpectedException.none();
@@ -64,7 +58,7 @@ public class BoltRoutingNeo4jDriverUrlTest {
 	private static org.neo4j.driver.Driver mockedDriver;
 
 	@Parameterized.Parameters
-	public static Iterable<? extends Object> data() {
+	public static Iterable<?> data() {
 		return Arrays.asList("jdbc:neo4j:neo4j://test", "jdbc:neo4j:neo4j+s://test", "jdbc:neo4j:neo4j+ssc://test");
 	}
 
@@ -73,30 +67,19 @@ public class BoltRoutingNeo4jDriverUrlTest {
 		mockedDriver = Mocker.mockDriver();
 	}
 
-	@Before
-	public void prepare() {
-		BoltRoutingNeo4jDriver.clearCache();
-	}
-
-	private String getBoltUrl() {
-		return completeValidUrl.replace("jdbc:neo4j:", "");
-	}
-
 	private String getPrefix() {
 		return completeValidUrl.split("://")[0];
 	}
 
-	@Test public void shouldConnectCreateConnection() throws SQLException, URISyntaxException {
-		PowerMockito.mockStatic(GraphDatabase.class);
-		Mockito.when(GraphDatabase.driver(Mockito.eq(new URI(getBoltUrl())), Mockito.eq(AuthTokens.none()), any(Config.class))).thenReturn(mockedDriver);
-
-		Neo4jDriver driver = new BoltRoutingNeo4jDriver();
+	@Test public void shouldConnectCreateConnection() throws SQLException {
+		Neo4jDriver driver = new BoltRoutingNeo4jDriver((routingUris, config, authToken, props) -> mockedDriver);
 		Connection connection = driver.connect(completeValidUrl, null);
 		assertNotNull(connection);
 	}
 
 	@Test public void shouldAcceptURL() throws SQLException {
-		Neo4jDriver driver = new BoltRoutingNeo4jDriver();
+		Neo4jDriver driver = new BoltRoutingNeo4jDriver((routingUris, config, authToken, props) -> mockedDriver);
+
 		assertTrue(driver.acceptsURL(getPrefix() + "://localhost:7687"));
 		assertTrue(driver.acceptsURL(getPrefix() + "://localhost:7687/"));
 		assertTrue(driver.acceptsURL(getPrefix() + "://192.168.0.1:7687"));
diff --git a/neo4j-jdbc-http/src/test/java/org/neo4j/jdbc/http/HttpNeo4jResultSetMetaDataTest.java b/neo4j-jdbc-http/src/test/java/org/neo4j/jdbc/http/HttpNeo4jResultSetMetaDataTest.java
index 66fd8b9b..e9d6d3a3 100644
--- a/neo4j-jdbc-http/src/test/java/org/neo4j/jdbc/http/HttpNeo4jResultSetMetaDataTest.java
+++ b/neo4j-jdbc-http/src/test/java/org/neo4j/jdbc/http/HttpNeo4jResultSetMetaDataTest.java
@@ -31,8 +31,9 @@ import java.util.List;
 import java.util.Map;
 
 import static org.junit.Assert.assertEquals;
-import static org.powermock.api.mockito.PowerMockito.mock;
-import static org.powermock.api.mockito.PowerMockito.when;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 /**
  * @author AgileLARUS
@@ -57,7 +58,7 @@ public class HttpNeo4jResultSetMetaDataTest {
 		row.add(1.2);
 		row.add(1.2F);
 		row.add(new HashMap<>());
-		row.add(new ArrayList());
+		row.add(new ArrayList<>());
 
 		map.put("row", row);
 
@@ -69,7 +70,7 @@ public class HttpNeo4jResultSetMetaDataTest {
 	}
 	@Test
 	public void getColumnClassNameShouldReturnTheCorrectValue() throws SQLException {
-		assertEquals(null, this.httpResultSetMetadata.getColumnClassName(1));
+		assertNull(this.httpResultSetMetadata.getColumnClassName(1));
 		assertEquals("java.lang.String", this.httpResultSetMetadata.getColumnClassName(2));
 		assertEquals("java.lang.Long", this.httpResultSetMetadata.getColumnClassName(3));
 		assertEquals("java.lang.Long", this.httpResultSetMetadata.getColumnClassName(4));