Spring Безопасность, JUnit: @WithUserДетали для пользователя, созданного в @Before
В тестах JUnit с помощью Spring MockMVC существует два метода аутентификации в качестве пользователя безопасности Spring: @WithMockUser
создает фиктивного пользователя с предоставленными учетными данными, @WithUserDetails
принимает имя пользователя и решает его правильную реализацию UserDetails
с пользовательским UserDetailsService
(UserDetailsServiceImpl
).
В моем случае, UserDetailsService
загружает пользователя из базы данных. Пользователь, которого я хочу использовать, был вставлен в метод @Before
тестового набора.
Однако мой UserDetailsServiceImpl
не находит пользователя.
В моем @Before
я вставляю пользователя следующим образом:
User u = new User();
u.setEMail("[email protected]");
u = userRepository.save(u);
И в UserDetailsServiceImpl
:
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = this.userRepository.findOneByEMail(username);
if (user == null)
throw new UsernameNotFoundException(String.format("No user found with username '%s'.", username));
return user;
}
Как я могу использовать учетную запись, созданную в @Before
, с помощью @WithUserDetails
?
Ответы
Ответ 1
К сожалению, вы не можете сделать легко @WithUserDetails
с @Before
, потому что spring @WithUserDetails
аннотации будут вызывать Spring безопасность контекста тестового слушателя перед запуском setUp
метода с @Before
.
Вот fooobar.com/questions/630749/... небольшая хитрость и ответ на ваш вопрос.
Ответ 2
@Inject
private EntityManager em;
@Inject
PlatformTransactionManager txManager;
@BeforeTransaction
public void setup() {
new TransactionTemplate(txManager).execute(status -> {
User u = new User();
u.setEMail("[email protected]");
em.save(u);
return null;
});
}
@AfterTransaction
public void cleanup() {
new TransactionTemplate(txManager).execute(status -> {
// Check if the entity is managed by EntityManager.
// If not, make it managed with merge() and remove it.
em.remove(em.contains(u) ? user1 : em.merge(u));
return null;
});
}
@Test
@Transactional
@WithUserDetails(value = "[email protected]", userDetailsServiceBeanName = "loadUserByUsername")
public void test() {
}
Ответ 3
Вы можете использовать @PostConstruct
вместо @Before
. Это помогло мне. Кто-нибудь может это подтвердить?