Spring Boot集成测试失败:checkIfUserIsNull断言不通过求助
集成测试失败排查:
assertTrue(userServiceImpl.checkIfUserIsNull(1L))返回false 运行UserServiceTest中的isUserNullCheck测试方法时,抛出如下断言错误:
org.opentest4j.AssertionFailedError: Expected :true Actual :false
相关代码
User实体类
@Entity @Table(name = "\"user\"") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") private Long id; @Column(name = "username") private String userName; @Column(name = "password") private String password; @Column(name = "first_name") private String firstName; @Column(name = "last_name") private String lastName; @Column(name = "email") private String email; @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinTable(name = "users_roles", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id")) private Collection<Role> roles; public User() { } public User(String userName, String password, String firstName, String lastName, String email) { this.userName = userName; this.password = password; this.firstName = firstName; this.lastName = lastName; this.email = email; } public User(String userName, String password, String firstName, String lastName, String email, Collection<Role> roles) { this.userName = userName; this.password = password; this.firstName = firstName; this.lastName = lastName; this.email = email; this.roles = roles; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Collection<Role> getRoles() { return roles; } public void setRoles(Collection<Role> roles) { this.roles = roles; } @Override public String toString() { return "User{" + "id=" + id + ", userName='" + userName + '\'' + ", password='" + "*********" + '\'' + ", firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + ", email='" + email + '\'' + ", roles=" + roles + '}'; } }
UserService接口
public interface UserService extends UserDetailsService { public Optional<User> findByUserName(String userName); public void save(CrmUser crmUser); void deleteById(Long theId); public boolean checkIfUserIsNull(long id); }
UserServiceImpl实现类
@Service @Transactional public class UserServiceImpl implements UserService { @Autowired private EntityManager entityManager; @Autowired private UserRepository userRepository; @Autowired private RoleRepository roleRepository; @Lazy @Autowired private BCryptPasswordEncoder passwordEncoder; private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class); @Override @Transactional public Optional<User> findByUserName(String userName) { // check the database if the user already exists return userRepository.findByUserName(userName); } @Override @Transactional public void save(CrmUser crmUser) { User user = new User(); // assign user details to the user object user.setUserName(crmUser.getUserName()); user.setPassword(passwordEncoder.encode(crmUser.getPassword())); user.setFirstName(crmUser.getFirstName()); user.setLastName(crmUser.getLastName()); user.setEmail(crmUser.getEmail()); // give user default role of "CUSTOMER" Optional<Role> roleCustomer = roleRepository.findRoleByName("ROLE_CUSTOMER"); log.info("The role " + roleCustomer); if (!roleCustomer.isPresent()) { throw new NoSuchElementException("The role is not found"); } else { user.setRoles(Collections.singletonList(roleCustomer.get())); } // save user in the database userRepository.save(user); } @Override @Transactional public void deleteById(Long theId) { Session currentSession = entityManager.unwrap(Session.class); Query theQuery = currentSession.createQuery("delete from User where id=:userId"); theQuery.setParameter("userId", theId); theQuery.executeUpdate(); } @Override @Transactional public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException { Optional<User> user = userRepository.findByUserName(userName); log.info("user is present: " + user.isPresent()); if (!user.isPresent()) { throw new UsernameNotFoundException("Invalid username or password."); } log.info("password: " + user.get().getPassword()); return new org.springframework.security.core.userdetails.User(user.get().getUserName(), user.get().getPassword(), mapRolesToAuthorities(user.get().getRoles())); } private Collection<? extends GrantedAuthority> mapRolesToAuthorities(Collection<Role> roles) { if (roles == null) { return Collections.emptyList(); } return roles.stream().map(role -> new SimpleGrantedAuthority(role.getName())).collect(Collectors.toList()); } public boolean checkIfUserIsNull(long id) { Optional<User> user = userRepository.findById(id); return user.isPresent(); } }
UserRepository
@Repository public interface UserRepository extends JpaRepository<User, Long> { Optional<User> findByUserName(String userName); }
application-test.properties配置
spring.datasource.url=jdbc:h2:mem:testdb;MODE=MySQL;INIT=CREATE SCHEMA IF NOT EXISTS "user"\\;SET SCHEMA "user";DB_CLOSE_DELAY=-1 spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password=password spring.datasource.initialization-mode=always spring.jpa.database-platform=org.hibernate.dialect.H2Dialect spring.h2.console.enabled=true spring.jpa.hibernate.ddl-auto=create-drop spring.jpa.show-sql = true sql.script.create.user1=INSERT INTO "user" (id,username,password,first_name,last_name,email) VALUES \\\n (1,'john','$2a$04$eFytJDGtjbThXa80FyOOBuFdK2IwjyWefYkMpiBEFlpBwDH.5PM0K','John','Doe','john@luv2code.com') sql.script.create.user2=INSERT INTO "user" (id,username,password,first_name,last_name,email) VALUES \\\n (2,'mary','$2a$04$eFytJDGtjbThXa80FyOOBuFdK2IwjyWefYkMpiBEFlpBwDH.5PM0K','Mary','Public','mary@luv2code.com') sql.script.create.user3=INSERT INTO "user" (id,username,password,first_name,last_name,email) VALUES \\\n (3,'susan','$2a$04$eFytJDGtjbThXa80FyOOBuFdK2IwjyWefYkMpiBEFlpBwDH.5PM0K','Susan','Adams','susan@luv2code.com') sql.script.create.role1=INSERT INTO `role` (id,name) VALUES (1,'ROLE_CUSTOMER') sql.script.create.role2=INSERT INTO `role` (id,name) VALUES (2,'ROLE_ADMIN') sql.script.create.users_roles.user1=INSERT INTO `users_roles` (user_id,role_id) VALUES (1, 1) sql.script.create.users_roles.user2=INSERT INTO `users_roles` (user_id,role_id) VALUES (2, 2) sql.script.create.users_roles.user3=INSERT INTO `users_roles` (user_id,role_id) VALUES (3, 2) sql.script.delete.user=DELETE FROM user sql.script.delete.role=DELETE FROM role sql.script.delete.users_roles=DELETE FROM users_roles
UserServiceTest测试类
@TestPropertySource("/application-test.properties") @SpringBootTest @RunWith(SpringRunner.class) public class UserServiceTest { @Autowired private static JdbcTemplate jdbc; @Autowired private UserServiceImpl userServiceImpl; private static final Logger log = LoggerFactory.getLogger(UserServiceTest.class); @Value("${sql.script.create.user1}") private String sqlCreateUser1; @Value("${sql.script.create.user2}") private String sqlCreateUser2; @Value("${sql.script.create.user3}") private String sqlCreateUser3; @Value("${sql.script.create.role1}") private String sqlCreateRole1; @Value("${sql.script.create.role2}") private String sqlCreateRole2; @Value("${sql.script.create.users_roles.user1}") private String sqlCreateUsersRolesUser1; @Value("${sql.script.create.users_roles.user3}") private String sqlCreateUsersRolesUser2; @Value("${sql.script.create.users_roles.user3}") private String sqlCreateUsersRolesUser3; @Value("${sql.script.delete.user}") private String sqlDeleteUser; @Value("${sql.script.delete.role}") private String sqlDeleteRole; @Value("${sql.script.delete.users_roles}") private String sqlDeleteUsersRoles; @BeforeEach public void setupDatabase() { jdbc.execute(sqlCreateUser1); jdbc.execute(sqlCreateUser2); jdbc.execute(sqlCreateUser3); jdbc.execute(sqlCreateRole1); jdbc.execute(sqlCreateRole2); jdbc.execute(sqlCreateUsersRolesUser1); jdbc.execute(sqlCreateUsersRolesUser2); jdbc.execute(sqlCreateUsersRolesUser3); } @Test public void isUserNullCheck() { assertTrue(userServiceImpl.checkIfUserIsNull(1L)); assertFalse(userServiceImpl.checkIfUserIsNull(0L)); } @AfterEach public void afterAll() { jdbc.execute(sqlDeleteUser); jdbc.execute(sqlDeleteRole); jdbc.execute(sqlDeleteUsersRoles); } }
问题定位与修复
1. JdbcTemplate注入失败
测试类中jdbc被声明为static,Spring无法注入静态字段,导致setupDatabase()执行时jdbc为null,没有实际插入测试数据。
修复:去掉static修饰符,改为实例字段:
@Autowired private JdbcTemplate jdbc;
2. SQL脚本引用错误
测试类中sqlCreateUsersRolesUser2错误引用了${sql.script.create.users_roles.user3},导致重复插入user3的角色关联数据,同时user2的关联数据缺失。
修复:修正引用的配置项:
@Value("${sql.script.create.users_roles.user2}") private String sqlCreateUsersRolesUser2;
3. 删除脚本表名未加引号
sql.script.delete.user=DELETE FROM user中,user是SQL关键字,H2执行时会报错,导致清理数据失败,影响后续测试。
修复:给表名添加引号:
sql.script.delete.user=DELETE FROM "user" sql.script.delete.role=DELETE FROM "role" sql.script.delete.users_roles=DELETE FROM "users_roles"
4. 方法命名歧义(可选优化)
checkIfUserIsNull方法名表达的是“检查用户是否为null”,但实际返回的是user.isPresent()(用户是否存在),命名与逻辑不符,容易混淆。
优化:修改方法名并更新接口定义:
// UserService接口 public boolean isUserExists(long id); // UserServiceImpl实现 @Override public boolean isUserExists(long id) { Optional<User> user = userRepository.findById(id); return user.isPresent(); } // 测试类调用 assertTrue(userServiceImpl.isUserExists(1L)); assertFalse(userServiceImpl.isUserExists(0L));
内容的提问来源于stack exchange,提问作者Connor
相关产品推荐
相关产品推荐

