gpt4 book ai didi

java - Spring 集成 jpa 存储库测试无法正常工作

转载 作者:行者123 更新时间:2023-12-02 02:04:47 25 4
gpt4 key购买 nike

我有一些非常奇怪的事情。我想测试我的存储库级别,并且需要测试是否可以使用相同的用户名保存 2 个用户(用户名字段在数据库中是唯一的)。这是我的数据库配置。

spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url= jdbc:postgresql://localhost:5432/tutorial_test
spring.datasource.username=postgres
spring.datasource.password=root

# General JPA properties
spring.jpa.show-sql=false

#Note: The last two properties on the code snippet above were added to suppress an annoying exception
# that occurs when JPA (Hibernate) tries to verify PostgreSQL CLOB feature.
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL9Dialect
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults = false

# Hibernate Specific properties
spring.jpa.properties.hibernate.format_sql=false
spring.jpa.hibernate.ddl-auto=create

我的实体类用户:

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "users")
public class User {

@Id
@SequenceGenerator(name = "user_id_seq_gen", sequenceName = "user_id_seq", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_id_seq_gen")
private Long id;
@Column(nullable = false, unique = true, length = 50)
@NotNull
@Length(min = 4, max = 50)
private String username;
@Column(nullable = false, length = 50)
@NotNull
@Length(min = 6, max = 50)
private String password;
@Column(nullable = false, unique = true, length = 100)
@NotNull
@Length(min = 6, max = 50)
private String email;
}

用户存储库:

public interface UserRepository extends JpaRepository<User, Long> {

boolean existsByUsername(String username);
boolean existsByEmail(String email);
User findByUsername(String username);
}

最后是我的测试类:

@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@TestPropertySource("/application-test.properties")
public class UserRepositoryTest {

@Autowired
private UserRepository userRepository;

@Before
public void insertData() {
user = new User(null, "Daimon", "123123", "krikkk998@mail.ru");
userRepository.save(user);
}

@After
public void cleanData(){
user = null;
userRepository.deleteAll();
}

@Test(expected = DataIntegrityViolationException.class)
public void registerUserWithExistingUsername() {
val user = new User(null, "Daimon", "123123", "glass999@mail.ru");
userRepository.save(user);
}

}

这个测试类的行为非常奇怪。它抛出一个异常,无法保存另一个实体,因为只有在 userRepository.deleteAll(); 之后用户名才是唯一的,为什么?好的,如果我删除 @After 方法,它根本不会抛出异常...同样,如果我添加 System.out.println(userRepository.findAll()); 保存第二个用户后,它抛出异常...这里发生了什么?当我启动应用程序时,这些方法都很有效。但在这些集成存储库中测试出了一些问题。我有另一个存储库测试类,我可以在其中保存父对象和一组未保存的子对象,当我从数据库中选择父对象时,它会为我提供一组具有 NULL id 的子对象...我不知道问题出在哪里,但我认为可能是配置问题?因为我重复一遍,当我启动应用程序时没有任何问题,并且一切都运行良好。如果您能帮助我,我会很高兴。

最佳答案

您看到的是 JPA 实现方式的副作用。当您保留合并一个实体时,大多数人将其视为保存该实体。这就是为什么调用这些方法的 Repository 方法被称为 save

但是在该阶段 (1) 没有发生数据库插入操作。相反,该实体只是被跟踪,并且会在某些事件发生时刷新:

  1. 事务的提交。
  2. 显式调用刷新。
  3. 根据您的配置,可能在查询之前(这里似乎是这种情况)。 这就是为什么在调用 findAll 时会出现异常。 deleteAll 的实现实际上涉及到 findAll,因此它也会触发异常。

(1) 实际上,根据您的 ID 生成策略,可能会发生插入

关于java - Spring 集成 jpa 存储库测试无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50981560/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com