/** * Executes Delete Operation immediately in current thread. * * <p>Notice: This is blocking I/O operation that should not be executed on the Main Thread, it * can cause ANR (Activity Not Responding dialog), block the UI and drop animations frames. So * please, call this method on some background thread. See {@link WorkerThread}. * * @return non-null result of Delete Operation. */ @SuppressWarnings("unchecked") @WorkerThread @NonNull @Override public DeleteResult executeAsBlocking() { try { final DeleteResolver<T> deleteResolver; if (explicitDeleteResolver != null) { deleteResolver = explicitDeleteResolver; } else { final ContentResolverTypeMapping<T> typeMapping = storIOContentResolver.lowLevel().typeMapping((Class<T>) object.getClass()); if (typeMapping == null) { throw new IllegalStateException( "Object does not have type mapping: " + "object = " + object + ", object.class = " + object.getClass() + ", " + "ContentProvider was not affected by this operation, please add type mapping for this type"); } deleteResolver = typeMapping.deleteResolver(); } return deleteResolver.performDelete(storIOContentResolver, object); } catch (Exception exception) { throw new StorIOException( "Error has occurred during Delete operation. object = " + object, exception); } }
@Test public void shouldFinishTransactionIfExceptionHasOccurredBlocking() { final StorIOSQLite storIOSQLite = mock(StorIOSQLite.class); final StorIOSQLite.Internal internal = mock(StorIOSQLite.Internal.class); when(storIOSQLite.internal()).thenReturn(internal); //noinspection unchecked final DeleteResolver<Object> deleteResolver = mock(DeleteResolver.class); when(deleteResolver.performDelete(same(storIOSQLite), anyObject())) .thenThrow(new IllegalStateException("test exception")); try { new PreparedDeleteCollectionOfObjects.Builder<Object>( storIOSQLite, singletonList(new Object())) .useTransaction(true) .withDeleteResolver(deleteResolver) .prepare() .executeAsBlocking(); failBecauseExceptionWasNotThrown(StorIOException.class); } catch (StorIOException expected) { IllegalStateException cause = (IllegalStateException) expected.getCause(); assertThat(cause).hasMessage("test exception"); verify(internal).beginTransaction(); verify(internal, never()).setTransactionSuccessful(); verify(internal).endTransaction(); verify(storIOSQLite).internal(); verify(deleteResolver).performDelete(same(storIOSQLite), anyObject()); verifyNoMoreInteractions(storIOSQLite, internal, deleteResolver); } }
@Test public void shouldFinishTransactionIfExceptionHasOccurredObservable() { final StorIOSQLite storIOSQLite = mock(StorIOSQLite.class); final StorIOSQLite.Internal internal = mock(StorIOSQLite.Internal.class); when(storIOSQLite.internal()).thenReturn(internal); //noinspection unchecked final DeleteResolver<Object> deleteResolver = mock(DeleteResolver.class); when(deleteResolver.performDelete(same(storIOSQLite), anyObject())) .thenThrow(new IllegalStateException("test exception")); final TestSubscriber<DeleteResults<Object>> testSubscriber = new TestSubscriber<DeleteResults<Object>>(); new PreparedDeleteCollectionOfObjects.Builder<Object>( storIOSQLite, singletonList(new Object())) .useTransaction(true) .withDeleteResolver(deleteResolver) .prepare() .createObservable() .subscribe(testSubscriber); testSubscriber.awaitTerminalEvent(); testSubscriber.assertNoValues(); testSubscriber.assertError(StorIOException.class); //noinspection ThrowableResultOfMethodCallIgnored StorIOException expected = (StorIOException) testSubscriber.getOnErrorEvents().get(0); IllegalStateException cause = (IllegalStateException) expected.getCause(); assertThat(cause).hasMessage("test exception"); verify(internal).beginTransaction(); verify(internal, never()).setTransactionSuccessful(); verify(internal).endTransaction(); verify(storIOSQLite).internal(); verify(deleteResolver).performDelete(same(storIOSQLite), anyObject()); verifyNoMoreInteractions(storIOSQLite, internal, deleteResolver); }