Save(...) не должно быть нулевым в весенних загрузочных тестах с Kotlin

Я пытаюсь проводить модульные тесты в простом приложении CRUD на Spring boot + Kotlin. Я уже провел тесты для других объектов и репозиториев, но у меня возникли проблемы с объектом User и репозиторием. Эта таблица связана с таблицей Team, возможно поэтому стандартная логика моих тестов не работает.

Версия Springboot "3.2.4"

Сущность

@Entity
@Table(name = "\"user\"")
@DynamicUpdate
class UserEntity(

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_generator")
    @SequenceGenerator(name = "user_generator", sequenceName = "user_id_seq", allocationSize = 1)
    @Column(name = "id")
    var userId: Int?,

    @Column(name = "email")
    val email: String,

    @Enumerated(EnumType.STRING)
    @Column(name = "role", columnDefinition = "user_role_enum", nullable = false)
    val role: Role,

    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(
        name = "user_teams_team",
        joinColumns = [JoinColumn(name = "user_id")],
        inverseJoinColumns = [JoinColumn(name = "team_id")]
    )
    val teams: Set<TeamEntity>? = null
)

@Entity
@Table(name = "team")
@DynamicUpdate
class TeamEntity(

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "team_generator")
    @SequenceGenerator(name = "team_generator", sequenceName = "team_id_seq", allocationSize = 1)
    @Column(name = "id")
    var teamId: Int?,

    @Column(name = "name_ru")
    val nameRu: String,

    @Column(name = "name_en")
    val nameEn: String,

    @Column(name = "name_kk")
    val nameKk: String
)

DTO

class UserDto(
    val email: String,
    val role: Role,
    val teams: List<Int>?
)
data class UserResponseDto(
    val userId: Int,
    val email: String,
    val role: Role,
    var teams: Set<TeamEntity>?
)

Усерсервицеимпл

package kt.cell.jobsapi.service.impl

import kt.cell.jobsapi.exception.InternalServerException
import kt.cell.jobsapi.exception.NotFoundException
import kt.cell.jobsapi.model.dto.*
import kt.cell.jobsapi.model.mapper.UserMapper
import kt.cell.jobsapi.repository.UserRepository
import kt.cell.jobsapi.service.UserService
import org.springframework.dao.DataIntegrityViolationException
import org.springframework.stereotype.Service
import java.util.*


@Service
class UserServiceImpl(
    val userRepository: UserRepository,
    val userMapper: UserMapper,
    val teamServiceImpl: TeamServiceImpl
) : UserService {

@Throws(NotFoundException::class)
override fun getUsers(): List<UserResponseDto> {
    val userEntityList = userRepository.findAll()

    return if (userEntityList.isNotEmpty()) {
        userEntityList.map { userMapper.toDto(it) }
    } else {
        throw NotFoundException("No users found")
    }
}

@Throws(Exception::class, DataIntegrityViolationException::class, NotFoundException::class)
override fun createUser(userDto: UserDto): UserResponseDto {
    teamServiceImpl.checkIfSuchTeamsExistOrThrowNotFoundException(userDto)

    val teamSet = teamServiceImpl.createTeamSetFromTeamIdsOrThrowNotFoundException(userDto)
    val savedUser = userRepository.save(userMapper.toEntity(userDto, teamSet))
    return userMapper.toDto(savedUser)
}

TeamServiceImpl

fun createTeamSetFromTeamIdsOrThrowNotFoundException(userDto: UserDto): MutableSet<TeamEntity> {
    val teamSet: MutableSet<TeamEntity> = mutableSetOf()
    userDto.teams?.forEach { teamId ->
        val teamEntity = teamRepository.findById(teamId)
            .orElseThrow { NotFoundException("There is no team with id: $teamId") }
        teamSet.add(teamEntity)
    }
    return teamSet
}
fun checkIfSuchTeamsExistOrThrowNotFoundException(userDto: UserDto) {
    val existingInDbTeamIdList = teamRepository.findAll().map { it.teamId!! }

    userDto.teams?.forEach { teamId ->
        if (teamId !in existingInDbTeamIdList) {
            throw NotFoundException("There is no team with id: $teamId")
        }
    }
}

Усерсервицеимплтестс

@ExtendWith(SpringExtension::class)
@TestInstance(TestInstance.Lifecycle.PER_METHOD)
class UserServiceImplTests {

@Mock
private lateinit var teamMapper: TeamMapper

@Mock
private lateinit var userRepository: UserRepository

@Mock
private lateinit var teamRepository: TeamRepository

@Mock
private lateinit var teamService: TeamServiceImpl

@Mock
private lateinit var userMapper: UserMapper

@InjectMocks
private lateinit var userService: UserServiceImpl

@Captor
private lateinit var userEntityCaptor: ArgumentCaptor<UserEntity>

@Test
fun createUser_Success() {
    val id = 1
    val teamEntity = TeamEntity(id, "testRu", "testEn", "testKk")
    val userEntity = UserEntity(id, "test", Role.OWNER, setOf(teamEntity))
    val userEntity1 = UserEntity(id, "test", Role.OWNER, setOf(teamEntity))
    val teamSet = mutableSetOf(teamEntity)
    val userDto = UserDto("test", Role.OWNER, listOf(1))
    val userResponseDto = UserResponseDto(id, "test", Role.OWNER, setOf(teamEntity))

    whenever(teamRepository.findAll()).thenReturn(listOf(teamEntity))
    whenever(teamRepository.findById(id)).thenReturn(Optional.of(teamEntity))
    whenever(userMapper.toEntity(userDto, teamSet)).thenReturn(userEntity)
    whenever(userRepository.save(userEntity)).thenReturn(userEntity)
    whenever(userMapper.toDto(userEntity)).thenReturn(userResponseDto)

    val result = userService.createUser(userDto)
    assertEquals(userResponseDto, result)

    verify(userRepository).save(userEntityCaptor.capture())
    val capturedEntity = userEntityCaptor.value
    assertNotNull(capturedEntity)
    assertEquals(userEntity, capturedEntity)

    verify(userRepository).save(userEntity)
    verify(teamRepository).findAll()
}

Это сама ошибка:

save(...) must not be null
java.lang.NullPointerException: save(...) must not be null
    at kt.cell.jobsapi.service.impl.UserServiceImpl.createUser(UserServiceImpl.kt:39)
    at kt.cell.jobsapi.service.impl.UserServiceImplTests.createUser_Success(UserServiceImplTests.kt:123)

я просто не понимаю где искать

ты забыл издеваться/заглушить teamService!(?;) ..или скорее ты "издевался" над этим, а не "издевался над инъекцией"...(пожалуйста, решите)

xerx593 06.07.2024 08:25

Кажется, я понял, что вы имеете в виду, но я не совсем понимаю, что мне нужно делать. Мой метод createTeamSetFromTeamIdsOrThrowNotFoundException находится в пакете «teamService» (а не в userService), так что, думаю, причина в этом. Но как мне вводить макеты? в userSerive или в teamService?

Роман 07.07.2024 09:31

Пожалуйста, покажите весь UserServiceImpl

Lesiak 07.07.2024 10:23

обновил код

Роман 07.07.2024 10:35
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Версия Java на основе версии загрузки
Версия Java на основе версии загрузки
Если вы зайдете на официальный сайт Spring Boot , там представлен start.spring.io , который упрощает создание проектов Spring Boot, как показано ниже.
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
0
4
57
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы не заглушаете teamServiceImpl.createTeamSetFromTeamIdsOrThrowNotFoundException(userDto), поэтому он возвращает ноль. В результате аргументы, переданные в toEntity, не совпадают, поэтому он также возвращает ноль.

спасибо за ответ, я тоже это проверю. Но теперь мой тест не доходит до похитителя, он провален раньше

Роман 07.07.2024 09:35

Обновил ответ

Lesiak 07.07.2024 17:49

вы точно получили ответ, я уже это понял. Спасибо за подсказку, которая помогла мне найти ответ!

Роман 08.07.2024 06:59

Другие вопросы по теме