我尝试测试一下。注意它是一个接口,所以我要测试 Spring 为我编写的类(作为练习,我正在学习测试)
package pp.spring_bootstrap.dao;
import org.springframework.data.jpa.repository.JpaRepository;
import pp.spring_bootstrap.models.Role;
import java.util.List;
public interface RoleDao extends JpaRepository<Role, Long> {
Role findByAuthority(String authority);
List<Role> findByAuthorityOrAuthority(String auth1, String auth2);
}
@Entity
@Table(name = "roles")
@Getter
@Setter
@EqualsAndHashCode
public class Role implements GrantedAuthority {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(name = "role", nullable = false, unique = true)
private String authority;
@ManyToMany(mappedBy = "authorities")
@EqualsAndHashCode.Exclude
private Set<User> userList;
public Role() {
}
public Role(String authority) {
this.authority = authority;
}
@Override
public String getAuthority() {
return authority;
}
// toString()
}
这是我的测试课:
package pp.spring_bootstrap.dao;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import pp.spring_bootstrap.models.Role;
import java.util.List;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
@SpringBootTest
class RoleDaoTest {
static RoleDao roleDao;
static final Role USER = new Role("USER");
static final Role ADMIN = new Role("ADMIN");
@Autowired
/*could be public, doesn't matter */ void setRoleDao(RoleDao roleDao) {
RoleDaoTest.roleDao = roleDao;
}
@BeforeAll
static void addSampleRows() {
roleDao.saveAll(List.of(USER, ADMIN));
}
@Test
void findByAuthority() {
assertThat(roleDao.findByAuthority("USER")).isEqualTo(USER);
}
@Test
void findByAuthorityOrAuthority() {
assertThat(roleDao.findByAuthorityOrAuthority("USER", "ADMIN")).asList().contains(USER, ADMIN);
}
}
用于测试的
properties
文件(在测试资源根目录内):
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
我得到了 NPE,因为没有注入任何东西。为什么?
java.lang.NullPointerException: Cannot invoke "pp.spring_bootstrap.dao.RoleDao.saveAll(java.lang.Iterable)" because "pp.spring_bootstrap.dao.RoleDaoTest.roleDao" is null
我不能用 setter 注入
static
字段吗?我认为这是你用来注入静态的技巧
您有多种选择可以让您的代码正常工作。第一个是使用
@BeforeEach
方法,不需要静态签名并确保在每个测试用例之前执行所需的规则。
@Autowired
private RoleDao roleDao;
@BeforeEach
void addSampleRows() {
roleDao.saveAll(List.of(USER, ADMIN));
}
或者,您可以添加
@TestInstance
注释。 JUnit 5 中的 @TestInstance
注释用于确定带注释的测试类的测试实例的生命周期。默认情况下它是PER_METHOD
。如果将其更改为 PER_CLASS
@BeforeAll
将不再需要是静态的:
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class RoleDaoTest {
将为所有测试方法创建测试类的单个实例。这样,您就可以在这些方法中使用依赖注入而不会出现任何问题。
你的课程将如下所示:
@SpringBootTest
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class RoleDaoTest {
@Autowired
private RoleDao roleDao;
static final Role USER = new Role("USER");
static final Role ADMIN = new Role("ADMIN");
@BeforeAll
void init() {
roleDao.saveAll(List.of(USER, ADMIN));
}
@Test
void findByAuthority() {
assertThat(roleDao.findByAuthority("USER")).isEqualTo(USER);
}
@Test
void findByAuthorityOrAuthority() {
assertThat(roleDao.findByAuthorityOrAuthority("USER", "ADMIN")).containsExactlyInAnyOrder(USER, ADMIN);
}
}
通过使用
PER_CLASS
生命周期 roleDao
被正确注入。
init()
方法(现在是实例方法而不是静态的)在所有测试方法之前运行一次。
您可以在@BeforeAll
中使用依赖注入,没有任何并发症。
但是,请记住,PER_CLASS
生命周期意味着所有测试方法共享测试类的相同实例。这可能会在测试方法之间引入副作用,因此如有必要,请务必确保重置 @BeforeEach
或 @AfterEach
方法中的任何共享状态。