Не могу запустить тесты Spring, "this.repository" is null

Рейтинг: 0Ответов: 2Опубликовано: 05.05.2023

Тест index() работает...

Код теста:

@Transactional
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class UserServiceTest {

    private static final User IVAN = new User(1, "Ivan", "123", "123", 0, Role.USER);

    @Mock
    private UserRepository userRepository;
    @InjectMocks
    private UserService userService =new UserService(userRepository,PASSWORD_ENCODER);

    @BeforeEach
    //void prepare(UserService userService) {
    void prepare() {
        System.out.println("Before each: " + this);
        //this.userService = new UserService();
    }

    @Test
    void index() {
        assertTrue(true);
    }

    @Test
    public void testGetByIdFromDb() {
        User user = userService.get(1); //  из базы
        assertEquals(1, (int) user.getId());
    }

}

Ошибка:

java.lang.NullPointerException: Cannot invoke "fun.dvornik.game.repository.UserRepository.getById(Object)" because "this.repository" is null

at fun.dvornik.game.service.UserService.get(UserService.java:60) at fun.dvornik.game.web.service.UserServiceTest.testGetByIdFromDb(UserServiceTest.java:43) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725) at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60) at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131) at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149) at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140) at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84) at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115) at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105) at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37) at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104) at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)

pom (версии библиотек):

<dependency>
  <groupId>org.junit.jupiter</groupId>
  <artifactId>junit-jupiter</artifactId>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-test</artifactId>
  <version>3.0.4</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.mockito</groupId>
  <artifactId>mockito-core</artifactId>
  <version>4.8.1</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.mockito</groupId>
  <artifactId>mockito-junit-jupiter</artifactId>
  <version>4.8.1</version>
  <scope>test</scope>
</dependency>

UserRepository почти пустой, UserService:

@Service("userService")
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
@AllArgsConstructor
public class UserService implements UserDetailsService {

private final UserRepository repository;
private final PasswordEncoder passwordEncoder;

public User create(User user) {
    Assert.notNull(user, "user must not be null");
    return prepareAndSave(user);
}

public void delete(int id) {
    repository.deleteById(id);
}

public User get(int id) {
    return repository.getById(id);
}

public User getByEmail(String email) {
    Assert.notNull(email, "email must not be null");
    if ( repository.findByEmailIgnoreCase(email).isPresent() )
        return  repository.findByEmailIgnoreCase(email).get();
    else
        throw new UsernameNotFoundException("User " + email + " is not found 2");
}

public List<User> getAll() {
    return repository.findAll();
}

public void update(User user) {
    Assert.notNull(user, "user must not be null");
    prepareAndSave(user);
}

public void update(UserTo userTo) {
    User user = get(userTo.id());
    prepareAndSave(UserUtil.updateFromTo(user, userTo));
}

public void enable(int id, boolean enabled) {
    User user = get(id);
    user.setEnabled(enabled);
    repository.save(user);  // !! need only for JDBC implementation
}

@Override
public AuthorizedUser loadUserByUsername(String email) throws UsernameNotFoundException {
    if ( repository.findByEmailIgnoreCase(email.toLowerCase()).isPresent() )
    {
        User user = repository.findByEmailIgnoreCase(email.toLowerCase()).get();
        return new AuthorizedUser(user);
    }
    else
        throw new UsernameNotFoundException("User " + email + " is not found");
}

Опыта с тестами нет, кроме rest api. Не знаю куда двигаться с проблемой.

Ответы

▲ 0Принят

Если хотите чтобы UserService был создан как мок и сработала аннотация @InjectMocks, вам не нужно создавать его инстанс. А вообще, чтобы тестить дата лэер jpa, в спринге есть аннотация @DataJpaTest. С ней будет создан репозиторий и база данных. Почитайте про нее.

▲ 0

Если я не ошибаюсь, проблема в том, что в тестовом классе не проинициализирован Mock-объект userRepository. Попробуй в методе явно его проиниализировать с помощь MockitoAnnotations.initMocks(this);. Этот метод инициализирует все объекты, помеченные аннотацией @Mock в переданном классе. Если этот mock-объект нужен в нескольких методах, тогда лучше написать setUp метод с аннотацией @BeforeEach, где будет выполнятся данные выше метод initMocks(this). Я бы так же посоветовал изучить работу @MockBean и в целом особенности тестирование с использованием фичей Спринга, раз уж ты уже работал с rest api. Тебе понравится =)