我有一个简单的存储库:

public interface ReviewRepository extends CrudRepository<ReviewEntity, Integer> {

  @Transactional(readOnly = true)
  List<ReviewEntity> findByProductId(int productId);
}

我想使用测试容器进行测试,我遵循了程序并编写了测试用例:

public abstract class MySqlTestBase {
  private static MySQLContainer database = new MySQLContainer("mysql:5.7.32");

  static {
    database.start();
  }

  @DynamicPropertySource
  static void databaseProperties(DynamicPropertyRegistry registry) {
    registry.add("spring.datasource.url", database::getJdbcUrl);
    registry.add("spring.datasource.username", database::getUsername);
    registry.add("spring.datasource.password", database::getPassword);
  }

}



@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class PersistTests extends MySqlTestBase {

  @Autowired
  private ReviewRepository repository;

  private ReviewEntity savedEntity;

  @BeforeEach
  void setupDb() {
    repository.deleteAll();

    ReviewEntity entity = new ReviewEntity(1, 2, "author1");
    savedEntity = repository.save(entity);
    assertEqualsReview(entity, savedEntity);
  }

  @Test
  void update() {
    savedEntity.setAuthor("author2");
    repository.save(savedEntity);



       ReviewEntity foundEntity = repository.findById(savedEntity.getId()).get();
       assertEquals(1, (long)foundEntity.getVersion());
       assertEquals("author2", foundEntity.getAuthor());
          }
    }

我的 comments 也是这样写的:

@Entity
public class ReviewEntity {

  @Id @GeneratedValue
  private int id;

  @Version
  private int version;

  private int productId;
  private int reviewId;
  private String author;

  public ReviewEntity(int productId, int reviewId, String author) {
        this.productId = productId;
        this.reviewId = reviewId;
        this.author = author;
}

          // setter and getter
    
    }

当我运行此测试时,它在assertEquals(1, (long)foundEntity.getVersion());行失败,并显示以下消息:

expected: <1> but was: <0>
Expected :1
Actual   :0

但我更新了ReviewEntity类,根据文档,@Version字段应该会自动增加,但不会发生这种情况.我的测试哪一部分错了?

推荐答案

如果您查看SimpleJpaRepository类中CrudRepository接口中save方法的默认实现,您将看到save方法的实现如下所示:

@Transactional
@Override
public <S extends T> List<S> saveAll(Iterable<S> entities) {

    Assert.notNull(entities, "Entities must not be null!");

    List<S> result = new ArrayList<S>();

    for (S entity : entities) {
        result.add(save(entity));
    }

    return result;
}

这意味着它被标记为@TransactionalRequired作为其传播级别(默认值)

Required传播的工作原理如下:

默认传播是必需的.弹簧判断是否存在

对于DataJpaTest条注释,注释部分说:

默认情况下,用@DataJpaTest注释的测试是事务性的,并且

因此,对于测试中的方法update,将创建一个事务,并将repository.save(savedEntity);中的save方法附加到该事务中.这意味着只有当事务成功提交并且我们现在知道这不会发生时,它才被提交.

这个问题probably的一个解决方法是用@Transactional(propagation = NOT_SUPPORTED)注释测试类以暂停当前正在运行的事务,然后对于repository.save(savedEntity);,将在save方法的末尾创建并提交一个事务,然后您可以继续测试.

Java相关问答推荐

Collections.binarySearch()使用Collections.reverseOrder()作为比较器返回-1

如何用javac编译Java类,即使对像java.lang.*这样的基本类也没有任何依赖关系?

我应该避免在Android中创建类并在运行时编译它们吗?

更新我们的一个文物后出现了严重的符号引用错误

当一个链表中间有一个循环时,它的松散部分会发生什么?

scanner 如何在执行hasNextLine一次后重新读取整个文件?

为什么我们不能实现两个接口,其中一个接口有相同的签名,其中一个接口有默认的实现在java?'

ApachePOI:不带换行的新行

基本时态运算的ISO-8601周数据表示法

Jlink选项&-strie-ative-Commands";的作用是什么?

Spring Boot Maven包

有谁能帮我修一下这个吗?使输出变得更加整洁

无法使用Open WebStart Java 8运行jnlp

当使用不同的参数类型调用时,为什么围绕Objects.equals的类型安全包装不会失败?

为什么我的登录终结点不能被任何请求访问?

按长度排序字符串数组

如何使用Hibernate v6.2构建NamingStrategy,以表名作为所有列的前缀?

Spring Boot Security-每个端点都被403禁止,Spring记录一个BasicErrorController#错误(HttpServlet请求)

放置在变量中的Java成员引用不相等

如何在java中从以百分比表示的经过时间和结束日期中找到开始日期