/** * @return a new {@link Spy} instance with an expectation initialized * @see #spy() * @see Spy#expect(int, Threads, Query) * @since 2.2 */ @Deprecated public static Spy expect(int allowedStatements, Query query, Threads threadMatcher) { return spy().expect(allowedStatements, query, threadMatcher); }
/** * Execute the {@link Executable#execute()} method, record the SQL queries * and return the {@link Spy} object with stats * @param executable code to test * @return statistics on executed queries * @throws RuntimeException if underlying code under test throws an Exception * @since 3.1 */ public static Spy execute(Executable executable) { return spy().execute(executable); }
/** * Execute the {@link Callable#call()} method, record the SQL queries * and return the {@link Spy.SpyWithValue} object with stats * @param callable code to test * @param <V> type of return value * @return statistics on executed queries * @throws Exception if underlying code under test throws an Exception * @since 3.1 */ @SuppressWarnings("unchecked") public static <V> Spy.SpyWithValue<V> call(Callable<V> callable) throws Exception { return spy().call(callable); } }
/** * Executes the {@link Runnable#run()} method on provided argument and verifies the expectations * @throws SniffyAssertionError if wrong number of queries was executed * @since 2.0 */ public C run(Runnable runnable) throws SniffyAssertionError { checkOpened(); try { runnable.run(); } catch (Throwable e) { throw verifyAndAddToException(e); } verify(); return self(); }
/** * Executes the {@link Callable#call()} method on provided argument and verifies the expectations * @throws SniffyAssertionError if wrong number of queries was executed * @since 2.0 */ public <V> SpyWithValue<V> call(Callable<V> callable) throws SniffyAssertionError { checkOpened(); V result; try { result = callable.call(); } catch (Throwable e) { throw verifyAndAddToException(e); } verify(); return new SpyWithValue<V>(result); }
@Test public void testGetXAConnectionWithCredentialsWithSocketOperation() throws Exception { JdbcDataSource h2DataSource = new JdbcDataSource(); h2DataSource.setURL("jdbc:h2:mem:"); JdbcDataSource targetDataSource = Mockito.spy(h2DataSource); when(targetDataSource.getXAConnection(anyString(), anyString())).then(invocation -> { Sniffy.logSocket(1, new InetSocketAddress(InetAddress.getLoopbackAddress(), 9876), 2, 3, 4); return invocation.callRealMethod(); }); SniffyDataSource sniffyDataSource = new SniffyDataSource(targetDataSource); try (Spy spy = Sniffy.expect(SqlQueries.exactQueries(1)).expect(TcpConnections.none()); Connection connection = sniffyDataSource.getXAConnection("sa","sa").getConnection()) { assertNotNull(connection); assertTrue(Proxy.isProxyClass(connection.getClass())); try (Statement statement = connection.createStatement()) { statement.execute("SELECT 1 FROM DUAL"); statement.getResultSet().next(); } assertTrue(spy.getSocketOperations(Threads.CURRENT, null, false).isEmpty()); } }
spy = spy.expect(new SqlQueries.SqlExpectation( Range.parse(sqlExpectation.count()).min, Range.parse(sqlExpectation.count()).max, spy = spy.expect(new TcpConnections.TcpExpectation( Range.parse(socketExpectation.connections()).min, Range.parse(socketExpectation.connections()).max, spy.execute(new Executable() { public void execute() throws Throwable { delegate.evaluate(); }).close(); } finally { if (null != disableSockets) {
@Test public void testSpyClosed() throws Exception { Spy spy = Sniffer.execute(() -> { executeStatement(); Thread thread = new Thread(BaseTest::executeStatement); thread.start(); thread.join(); }).expectAtMostOnce(Threads.OTHERS); spy.close(); try { spy.verify(1); } catch (Spy.SpyClosedException e) { assertNotNull(e); assertNotNull(e.getCloseStackTrace()); assertNotNull(e.getCloseStackTrace()[1]); StackTraceElement stackTraceElement = e.getCloseStackTrace()[1]; assertEquals("io.sniffy.SnifferTest", stackTraceElement.getClassName()); assertEquals("testSpyClosed", stackTraceElement.getMethodName()); } }
/** * @return a new {@link Spy} instance with an expectation initialized * @see #spy() * @see Spy#expectAtMostOnce(Threads) * @since 2.0 */ @Deprecated public static Spy expectAtMostOnce(Threads threadMatcher) { return spy().expectAtMostOnce(threadMatcher); }
/** * @return a new {@link Spy} instance with an expectation initialized * @see #spy() * @see Spy#expectAtLeast(int, Query) * @since 2.2 */ @Deprecated public static Spy expectAtLeast(int allowedStatements, Query query) { return spy().expectAtLeast(allowedStatements, query); }
/** * Alias for {@link #verify()} method; it is useful for try-with-resource API: * <pre> * <code> * {@literal @}Test * public void testTryWithResourceApi() throws SQLException { * final Connection connection = DriverManager.getConnection("sniffer:jdbc:h2:mem:", "sa", "sa"); * try (@SuppressWarnings("unused") Spy s = Sniffer.expectAtMostOnce(); * Statement statement = connection.createStatement()) { * statement.execute("SELECT 1 FROM DUAL"); * } * } * } * </code> * </pre> * @since 2.0 */ public void close() { try { verify(); } finally { Sniffy.removeSpyReference(selfReference); closed = true; StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); closeStackTrace = new StackTraceElement[stackTrace.length - 1]; System.arraycopy(stackTrace, 1, closeStackTrace, 0, stackTrace.length - 1); } }
@Test public void testVerifyMultipleFailures() throws Exception { try { Sniffer.expectAtLeast(1, Threads.CURRENT).expectAtLeast(1, Threads.OTHERS).verify(); } catch (WrongNumberOfQueriesError e) { assertNotNull(e); assertNotNull(e.getCause()); assertTrue(WrongNumberOfQueriesError.class.isAssignableFrom(e.getCause().getClass())); assertNull(e.getCause().getCause()); } }
@Test public void testSpyRemovedOnClose() throws Exception { Spy spy = Sniffy.spy(); spy.close(); Sniffy.registeredSpies.stream(). filter(spyReference -> spyReference.get() == spy). forEach(spyReference -> fail("Spy was not removed from Sniffer observers")); }
@Override public <T extends Spy<T>> Spy<T> verify(Spy<T> spy) throws TcpConnectionsExpectationError { Map<SocketMetaData, SocketStats> socketOperations = spy.getSocketOperations(threads, host, true); Set<Integer> connectionIds = new HashSet<Integer>(); for (SocketMetaData socketMetaData : socketOperations.keySet()) { connectionIds.add(socketMetaData.connectionId); } int numConnections = connectionIds.size(); if ((-1 != max && numConnections > max) || (-1 != min && numConnections < min)) { throw new TcpConnectionsExpectationError(this, socketOperations, numConnections); } return spy; }
/** * Execute the {@link Runnable#run()} method, record the SQL queries * and return the {@link Spy} object with stats * @param runnable code to test * @return statistics on executed queries * @since 3.1 */ public static Spy run(Runnable runnable) { return spy().run(runnable); }
@Override public <T extends Spy<T>> Spy<T> verify(Spy<T> spy) throws SniffyAssertionError { int numQueries = 0; int numRows = 0; for (Map.Entry<StatementMetaData, SqlStats> entry : spy.getExecutedStatements(threads, true).entrySet()) { if ((ANY == type && SYSTEM != entry.getKey().query) || type == entry.getKey().query) { SqlStats sqlStats = entry.getValue(); numQueries += sqlStats.queries.intValue(); numRows += sqlStats.rows.intValue(); } } if (numQueries > maxQueries || numQueries < minQueries) { throw new WrongNumberOfQueriesError( threads, type, minQueries, maxQueries, numQueries, spy.getExecutedStatements(threads, true).keySet() ); } if (numRows > maxRows || numRows < minRows) { throw new WrongNumberOfRowsError( threads, type, minRows, maxRows, numRows, spy.getExecutedStatements(threads, true) ); } return spy; }
@Test public void testGetConnectionWithCredentialsWithSocketOperation() throws Exception { JdbcDataSource h2DataSource = new JdbcDataSource(); h2DataSource.setURL("jdbc:h2:mem:"); JdbcDataSource targetDataSource = Mockito.spy(h2DataSource); when(targetDataSource.getConnection(anyString(), anyString())).then(invocation -> { Sniffy.logSocket(1, new InetSocketAddress(InetAddress.getLoopbackAddress(), 9876), 2, 3, 4); return invocation.callRealMethod(); }); SniffyDataSource sniffyDataSource = new SniffyDataSource(targetDataSource); try (Spy spy = Sniffy.expect(SqlQueries.exactQueries(1)).expect(TcpConnections.none()); Connection connection = sniffyDataSource.getConnection("sa","sa")) { assertNotNull(connection); assertTrue(Proxy.isProxyClass(connection.getClass())); try (Statement statement = connection.createStatement()) { statement.execute("SELECT 1 FROM DUAL"); statement.getResultSet().next(); } assertTrue(spy.getSocketOperations(Threads.CURRENT, null, false).isEmpty()); } }
/** * Executes the {@link Runnable#run()} method on provided argument and verifies the expectations * @throws SniffyAssertionError if wrong number of queries was executed * @since 2.0 */ public C run(Runnable runnable) throws SniffyAssertionError { checkOpened(); try { runnable.run(); } catch (Throwable e) { throw verifyAndAddToException(e); } verify(); return self(); }
/** * Executes the {@link Callable#call()} method on provided argument and verifies the expectations * @throws SniffyAssertionError if wrong number of queries was executed * @since 2.0 */ public <V> SpyWithValue<V> call(Callable<V> callable) throws SniffyAssertionError { checkOpened(); V result; try { result = callable.call(); } catch (Throwable e) { throw verifyAndAddToException(e); } verify(); return new SpyWithValue<V>(result); }
/** * @return a new {@link Spy} instance with an expectation initialized * @see #spy() * @see Spy#expectAtMostOnce(Threads, Query) * @since 2.2 */ @Deprecated public static Spy expectAtMostOnce(Threads threadMatcher, Query query) { return spy().expectAtMostOnce(threadMatcher, query); }