/**
   * 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);
    }