NullPointer Ошибка при попытке использовать метод в тесте - PullRequest
0 голосов
/ 17 апреля 2020

Здравствуйте, я новичок в Junit, и в настоящее время я пишу модульный тест, используя Junit 5 для этого класса:

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
        Optional<User> user = userRepository.findByEmail(email);

        user.orElseThrow(() -> new UsernameNotFoundException("Not found: " + email));

        return user.map(UserDetailsImpl::new).get();
    }
}

Ниже приведен класс тестирования:

class UserDetailsServiceImplTest {

    private static UserDetailsServiceImpl userDetailsServiceImpl;

    String email;
    /*User mockedUser;
    UserRepository userRepository;
    UserDetails userDetails;*/

    @BeforeAll
    static void setup() {
        userDetailsServiceImpl = new UserDetailsServiceImpl();
    }

    @Test
    void testLoadUserByUsername() {
        /*userRepository = mock(UserRepository.class);
        mockedUser = mock(User.class);

        Optional<User> user = Optional.of(mockedUser);

        when(userRepository.findByEmail(email)).thenReturn(user);
        assertEquals(userRepository.findByEmail(email), user);*/

        UserDetails userDetails = userDetailsServiceImpl.loadUserByUsername(email);
        assertTrue(userDetails instanceof UserDetails);
    }
}

Я получаю:

[ОШИБКА] Выполнено тестов: 1, сбоев: 0, ошибок: 1, пропущено: 0, истекло время: 5.108 с <<< НЕУДАЧИ! - в com.example. kanban .UserDetailsServiceImplTest [ОШИБКА] testLoadUserByUsername Истекшее время: 0,111 с <<< ОШИБКА! java .lang.NullPointerException в com.example. kanban .UserDetailsServiceImplTest.testLoadUserByUsername (UserDetailsServiceImplTest. java: 55) </p>

    [INFO] Running com.example.kanban.WebSecurityConfigTest
    [INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 s - in com.example.kanban.WebSecurityConfigTest
    2020-04-18 13:36:56.910  INFO 9180 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'
    2020-04-18 13:36:56.910  INFO 9180 --- [extShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
    2020-04-18 13:36:56.918  INFO 9180 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
    2020-04-18 13:36:56.934  INFO 9180 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.
    [INFO]
    [INFO] Results:
    [INFO]
    [ERROR] Errors:
    [ERROR]   UserDetailsServiceImplTest.testLoadUserByUsername:55 » NullPointer
    [INFO]
    [ERROR] Tests run: 4, Failures: 0, Errors: 1, Skipped: 0
    [INFO]
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD FAILURE
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time:  8.708 s
    [INFO] Finished at: 2020-04-18T13:36:57+02:00
    [INFO] ------------------------------------------------------------------------
    [ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.22.2:test (default-test) on project kanban: There are test failures.

Я пытался вернуть userRepository.findByEmail(email) метод возврата сделать ошибку peri sh (мои попытки закомментированы), но я не могу справиться с этой проблемой.

Ответы [ 2 ]

3 голосов
/ 18 апреля 2020

Если вы создадите экземпляр UserDetailsServiceImpl самостоятельно и не позволите Spring сделать это - ничего не будет введено. Это то, что вы делаете в методе @BeforeAll, потому что вы используете инъекцию на основе поля, но вы этого не видите.

Если вы хотите продолжать использовать этот метод инъекции, вам нужно разрешить впрыск пружины в тесте. UserDetailsServiceImpl.

. Для этого вам нужно добавить @SpringBootTest к вашему тестовому классу:

@SpringBootTest
class UserDetailsServiceImplTest {

    @Autowired
    private UserDetailsServiceImpl userDetailsServiceImpl;
}

Но, похоже, вы хотите насмехаться над UserRespository (и для модульного тестирования это лучший выбор) чтобы сделать это, самое простое и понятное ожидание, чтобы это сделать, это обновить информацию о том, как вы внедряете и используете инжектор конструктора (подробнее об этом в документации )

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    private final UserRepository userRepository;
    public UserDetailsServiceImpl(UserRepository userRepository) {
        this.userRepository = userRepository
    }
    @Override
    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
        Optional<User> user = userRepository.findByEmail(email);

        user.orElseThrow(() -> new UsernameNotFoundException("Not found: " + email));

        return user.map(UserDetailsImpl::new).get();
    }
}

и измените ваш тест, как простой модульный тест:

class UserDetailsServiceImplTest {

    private UserDetailsServiceImpl userDetailsServiceImpl;
    private UserRepository userRepository;

    @BeforeEach
    void setup() {
        userRepository = mock(UserRepository.class)
        userDetailsServiceImpl = new UserDetailsServiceImpl(userRepository);
    }

    @Test
    void testLoadUserByUsername() {
        mockedUser = mock(User.class);

        Optional<User> user = Optional.of(mockedUser);

        when(userRepository.findByEmail(email)).thenReturn(user);
        assertEquals(userRepository.findByEmail(email), user);

        UserDetails userDetails = userDetailsServiceImpl.loadUserByUsername(email);
        assertTrue(userDetails instanceof UserDetails);
    }
}

Точно так же, как @bhdrkn предложил вам прочитать больше о каркасе и внедрении зависимостей в целом. А также о модульном тестировании.

1 голос
/ 18 апреля 2020

добро пожаловать в Stackoverflow.

UserRepository в UserDetailsServiceImpl не подключается автоматически / вводится в модульном тесте, поскольку не инициализирован контекст пружины. Вы можете проверить этот вид зависимости, используя макеты. Вы можете проверить mockito для этого. В качестве альтернативы, вы можете попытаться инициализировать Spring Context для тестов, но я не советую это делать.

Помимо моего ответа у меня также есть пара предложений:

  1. Знай свои рамки наизусть. Они не просто волхвы c. Поймите, как работает пружина и как работает аннотация Autowired под капотом.

  2. Если вы новичок в внедрении зависимостей, я настоятельно рекомендую это сообщение в блоге , в котором объясняются основы.

  3. У вас уже есть комментарии, которые подсказывают вам решение. Я полагаю, что они пытаются помочь вам, не просто предоставив ответ, но вместо этого помогая вам самостоятельно найти проблему.

  4. Если вам нужен пример, где тестовый модуль Spring Boot протестирован с mockito, вы можете проверить этот репозиторий .

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...