You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 13:02:00