@Test
    public void
        shouldThrowExceptionIfNoTypeMappingWasFoundWithTransactionWithoutAffectingDbBlocking() {
      final StorIOSQLite storIOSQLite = mock(StorIOSQLite.class);
      final StorIOSQLite.Internal internal = mock(StorIOSQLite.Internal.class);

      when(storIOSQLite.lowLevel()).thenReturn(internal);

      when(storIOSQLite.put()).thenReturn(new PreparedPut.Builder(storIOSQLite));

      final List<TestItem> items = asList(TestItem.newInstance(), TestItem.newInstance());

      final PreparedPut<PutResults<TestItem>> preparedPut =
          storIOSQLite.put().objects(items).useTransaction(true).prepare();

      try {
        preparedPut.executeAsBlocking();
        failBecauseExceptionWasNotThrown(StorIOException.class);
      } catch (StorIOException expected) {
        // it's okay, no type mapping was found
        assertThat(expected).hasCauseInstanceOf(IllegalStateException.class);
      }

      verify(storIOSQLite).put();
      verify(storIOSQLite).lowLevel();
      verify(internal).typeMapping(TestItem.class);
      verify(internal, never()).insert(any(InsertQuery.class), any(ContentValues.class));
      verify(internal, never()).update(any(UpdateQuery.class), any(ContentValues.class));
      verifyNoMoreInteractions(storIOSQLite, internal);
    }
    @Test
    public void verifyBehaviorInCaseOfExceptionWithoutTransactionCompletable() {
      final StorIOSQLite storIOSQLite = mock(StorIOSQLite.class);
      final StorIOSQLite.Internal internal = mock(StorIOSQLite.Internal.class);

      when(storIOSQLite.lowLevel()).thenReturn(internal);

      //noinspection unchecked
      final PutResolver<Object> putResolver = mock(PutResolver.class);

      when(putResolver.performPut(same(storIOSQLite), anyObject()))
          .thenThrow(new IllegalStateException("test exception"));

      final List<Object> objects = singletonList(new Object());

      final TestSubscriber<PutResults<Object>> testSubscriber =
          new TestSubscriber<PutResults<Object>>();

      new PreparedPutCollectionOfObjects.Builder<Object>(storIOSQLite, objects)
          .useTransaction(false)
          .withPutResolver(putResolver)
          .prepare()
          .asRxCompletable()
          .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");

      // Main checks of this test
      verify(internal, never()).beginTransaction();
      verify(internal, never()).setTransactionSuccessful();
      verify(internal, never()).endTransaction();

      verify(storIOSQLite).lowLevel();
      verify(storIOSQLite).defaultScheduler();
      verify(putResolver).performPut(same(storIOSQLite), anyObject());
      verifyNoMoreInteractions(storIOSQLite, internal, putResolver);
    }
    @Test
    public void verifyBehaviorInCaseOfExceptionWithoutTransactionBlocking() {
      final StorIOSQLite storIOSQLite = mock(StorIOSQLite.class);
      final StorIOSQLite.Internal internal = mock(StorIOSQLite.Internal.class);

      when(storIOSQLite.lowLevel()).thenReturn(internal);

      //noinspection unchecked
      final PutResolver<Object> putResolver = mock(PutResolver.class);

      when(putResolver.performPut(same(storIOSQLite), anyObject()))
          .thenThrow(new IllegalStateException("test exception"));

      final List<Object> objects = singletonList(new Object());

      try {
        new PreparedPutCollectionOfObjects.Builder<Object>(storIOSQLite, objects)
            .useTransaction(false)
            .withPutResolver(putResolver)
            .prepare()
            .executeAsBlocking();

        failBecauseExceptionWasNotThrown(StorIOException.class);
      } catch (StorIOException expected) {
        IllegalStateException cause = (IllegalStateException) expected.getCause();
        assertThat(cause).hasMessage("test exception");

        // Main checks of this test
        verify(internal, never()).beginTransaction();
        verify(internal, never()).setTransactionSuccessful();
        verify(internal, never()).endTransaction();

        verify(storIOSQLite).lowLevel();
        verify(putResolver).performPut(same(storIOSQLite), anyObject());
        verifyNoMoreInteractions(storIOSQLite, internal, putResolver);
      }
    }
    @Test
    public void
        shouldThrowExceptionIfNoTypeMappingWasFoundWithTransactionWithoutAffectingDbAsCompletable() {
      final StorIOSQLite storIOSQLite = mock(StorIOSQLite.class);
      final StorIOSQLite.Internal internal = mock(StorIOSQLite.Internal.class);

      when(storIOSQLite.lowLevel()).thenReturn(internal);

      when(storIOSQLite.put()).thenReturn(new PreparedPut.Builder(storIOSQLite));

      final List<TestItem> items = asList(TestItem.newInstance(), TestItem.newInstance());

      final TestSubscriber<PutResults<TestItem>> testSubscriber =
          new TestSubscriber<PutResults<TestItem>>();

      storIOSQLite
          .put()
          .objects(items)
          .useTransaction(true)
          .prepare()
          .asRxCompletable()
          .subscribe(testSubscriber);

      testSubscriber.awaitTerminalEvent();
      testSubscriber.assertNoValues();
      assertThat(testSubscriber.getOnErrorEvents().get(0))
          .isInstanceOf(StorIOException.class)
          .hasCauseInstanceOf(IllegalStateException.class);

      verify(storIOSQLite).put();
      verify(storIOSQLite).lowLevel();
      verify(storIOSQLite).defaultScheduler();
      verify(internal).typeMapping(TestItem.class);
      verify(internal, never()).insert(any(InsertQuery.class), any(ContentValues.class));
      verify(internal, never()).update(any(UpdateQuery.class), any(ContentValues.class));
      verifyNoMoreInteractions(storIOSQLite, internal);
    }