2

I am using Spring Boot (2.1.4) and attempt to write a simple unit test to delete an entity. The entity (some parts omitted for brevity):

@Entity
@Table(name = "my_table")
public class MyEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    protected Long id;

    @Getter
    @Type(type="uuid-char")
    @Column(name = "attribute_id", unique = true, nullable = false)
    protected UUID attributeId;

    @Version
    protected Date version;

    @Getter
    @Column(unique = true, nullable = false)
    protected String value;

}

The entity has a simple repository:

public interface MyEntityRepository extends PagingAndSortingRepository<MyEntity, Long> {

    Optional<MyEntity> findByMyId(UUID id);

}

The unit tests uses an in memory database:

spring:
  jpa:
    database: H2
    database-platform: org.hibernate.dialect.H2Dialect
    hibernate:
      ddl-auto: create
    properties:
      hibernate.cache.use_second_level_cache: false
      hibernate.cache.use_query_cache: false
    generate-ddl: true
  datasource:
    url: jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false
    username: sa
    password: sa
    driver-class-name: org.h2.Driver

The tests itself (using database-rider):

@Test
@DataSet(value = INITIAL, transactional = true)
void delete() {
    Optional<MyEntity> v = repository.findByMyId(SECOND.getAttributeId());
    assertThat(v.isPresent()).isTrue();
    repository.delete(v.get());
    v = repository.findByMyId(SECOND.getAttributeId());
}

The last line in the test throws the following exception:

Caused by: org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
    at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:67)
    at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:54)
    at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:46)
    at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:3480)
    at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:3737)
    at org.hibernate.action.internal.EntityDeleteAction.execute(EntityDeleteAction.java:99)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:478)

all the other tests for save and find are working as expected, only using delete is causing this.

I've tried several suggested solutions from other posts (this is a similar post but it didn't solve my problem)

apines
  • 1,254
  • 14
  • 36

2 Answers2

2

Have you tried to use @ExpectedDataSet? in this way you let dbrider assert the state of the database after test execution:

@Test
@DataSet(value = INITIAL, transactional = true)
@ExpectedDataSet("expected.yml")
void delete() {
    Optional<MyEntity> v = repository.findByMyId(SECOND.getAttributeId());
    assertThat(v.isPresent()).isTrue();
    repository.delete(v.get());
    //v = repository.findByMyId(SECOND.getAttributeId()); let dbrider assert that for you
}
rmpestano
  • 838
  • 1
  • 8
  • 17
1

You are trying to access v = repository.findByMyId(SECOND.getAttributeId()); after performing deletion which is not committed yet.

Sim Sam
  • 121
  • 1
  • 7
  • 1
    How do I commit it prior to the assertion in the test? Didn't encounter this kind of behavior before in deletions, not sure what is different. – apines May 20 '19 at 10:55