春季集成jpa存储库测试无法正常运行

时间:2018-06-22 06:00:52

标签: java spring spring-data-jpa integration-testing

我有一些很奇怪的东西。我想测试我的存储库级别,并且需要测试是否可以用相同的用户名保存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;
}

UserRepository:

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的子对象... 我不知道这是什么问题,但我认为可能是在配置中?因为我重复了,所以当我启动应用程序时没有问题,并且一切都很好。如果您能帮助我,我会很高兴。

2 个答案:

答案 0 :(得分:2)

您看到的是JPA实现方式的副作用。当您persistmerge实体时,大多数人将其视为保存实体。因此,调用这些方法的Repository方法被称为save

但是在该阶段(1)并没有插入数据库。取而代之的是,只跟踪实体,它会在某些事件时刷新:

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

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

答案 1 :(得分:0)

plugins { id 'com.github.blindpirate.gogradle' version '0.8.1' } golang { packagePath = 'github.com/apache/incubator-openwhisk-cli' as String buildTags = (rootProject.findProperty('goTags')?:'').split(',') } dependencies { golang { // BEGIN - Imported from Godeps build(['name':'golang.org/x/sys/unix', 'version':'7f918dd405547ecb864d14a8ecbbfe205b5f930f', 'transitive':false]) build(['name':'gopkg.in/yaml.v2', 'version':'cd8b52f8269e0feb286dfeef29f8fe4d5b397e0b', 'transitive':false]) build(['name':'github.com/ghodss/yaml', 'version':'0ca9ea5df5451ffdf184b4428c902747c2c11cd7', 'transitive':false]) build(['name':'github.com/apache/incubator-openwhisk-client-go/whisk','version':'e452b524cd745f71c913c5acccf72a8daba6dc71','transitive':false]) // END - Imported from Godeps test name:'github.com/stretchr/testify', version:'b91bfb9ebec76498946beb6af7c0230c7cc7ba6c', transitive:false //, tag: 'v1.2.0' test name:'github.com/spf13/viper', version:'aafc9e6bc7b7bb53ddaa75a5ef49a17d6e654be5', transitive:false test name:'github.com/cpuguy83/go-md2man/md2man', version:'1d903dcb749992f3741d744c0f8376b4bd7eb3e1', transitive:false //, tag:'v1.0.7' test name:'github.com/davecgh/go-spew/spew', version:'346938d642f2ec3594ed81d874461961cd0faa76', transitive:false //, tag:'v1.1.0' test name:'github.com/pmezard/go-difflib/difflib', version:'792786c7400a136282c1664665ae0a8db921c6c2', transitive:false } } 在运行测试之前运行。它在此处插入一个用户名为“ Daimon”的用户

@Before是您的测试。它试图插入一个用户名已经存在的用户“ Daimon”(因为它已插入@Test中。这就是抛出异常的原因。

@Before在测试后运行。它将删除所有用户。