I am writing a jUnit5 test to test my getUserByEmail(String email) using Mockito and when running the test, it is failing.
#SpringBootTest
#ExtendWith(MockitoExtension.class)
class UserServiceTest {
#MockBean
private UsersRepository userRepository;
#Autowired
private UserService userService;
#Test
void check_email_existInDB_thenReturn_True() {
// given - precondition or setup
UserDetails userdetails2 = new UserDetails(101L, "Anthony Ji", "anthony#gmail.com", "password2");
userRepository.save(userdetails2);
// when - action or behaviour that we are going test
when(userRepository.save(userdetails2)).thenReturn(userdetails2);
// then - verify the result or output using assert statements
assertEquals(userdetails2.getEmail(), userService.getUserByEmail("anthony#gmail.com"));
//assertTrue(userService.getUserByEmail(userdetails2.getEmail()));
}
}
This is my interface with extending of JPARepository
public interface UsersRepository extends JpaRepository<UserDetails, Long>{
}
This is my service level class
#Service
public interface UserService {
public Optional<UserDetails> getUserByEmail(String email);
public UserDetails saveUserDetails(UserDetails userDetails);
}
And this is the serviceImpl Class..
#Service
public class UserServiceImpl implements UserService{
#Autowired
private UsersRepository userRepository;
#Override
public Optional<UserDetails> getUserByEmail(String email) {
List<UserDetails> allUsers = this.userRepository.findAll();
Optional<UserDetails> userInfo = allUsers.stream().filter(user -> user.getEmail().equalsIgnoreCase(email)).findAny();
return userInfo;
}
#Override
public UserDetails saveUserDetails(UserDetails userDetails) {
UserDetails savedUserDetails = this.userRepository.save(userDetails);
return savedUserDetails;
}
}
and finally, this is my controller class while using jersey framework.
#Path(value = "/user")
public class RegistrationResources {
private static Logger logger = LoggerFactory.getLogger(RegistrationResources.class);
#Autowired
private UserService userService;
#POST
#Path("/registration")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public Response registerUser(UserDetails userDetails, #Context UriInfo uriInfo) {
logger.info("Inside the registration resource and registering the user");
boolean isEmailExists = isEmailExists(userDetails.getEmail());
if(isEmailExists) {
logger.info("Email Already Registered");
return Response.status(404).entity("Email Address already registered").build();
}
else {
this.userService.saveUserDetails(userDetails);
logger.info("User successfully registered");
return Response.status(200).entity("User successfully registered").build();
}
}
public boolean isEmailExists(String email) {
UserDetails userByEmail = this.userService.getUserByEmail(email).orElse(null);
if(userByEmail == null) {
return false;
}
return true;
}
I tried as above explained in the code.
Related
I have a problem when testing a method with using passwordencoder:
Cannot invoke "org.springframework.security.crypto.password.PasswordEncoder.encode(java.lang.CharSequence)" because the return value of "com.store.restAPI.user.UserConfig.passwordEncoder()" is null`
Thats my test class method:
#ExtendWith(MockitoExtension.class)
class UserServiceTest {
private UserService underTest;
#Mock
private UserRepository userRepository;
#Mock
private UserConfig userConfig;
#BeforeEach
void setUp(){
underTest = new UserService(userRepository, userConfig);
}
#Test
void itShouldFindAllUsers() {
//when
underTest.findAll();
//then
verify(userRepository).findAll();
}
#Test
void addNewUser() {
//given
User expected = new User(
"mateusz#gmail.com",
"123"
);
//when
underTest.addNewUser(expected);
//then
ArgumentCaptor<User> userArgumentCaptor =
ArgumentCaptor.forClass(User.class);
verify(userRepository).save(userArgumentCaptor.capture());
User capturedUser = userArgumentCaptor.getValue();
assertThat(capturedUser).isEqualTo(expected);
}
#Test
#Disabled
void loginUser() {
}
}
And thats UserService method that i want to test:
#Service
public class UserService {
private final UserRepository userRepository;
private final UserConfig userConfig;
#Autowired
public UserService(UserRepository userRepository, UserConfig userConfig) {
this.userRepository = userRepository;
this.userConfig = userConfig;
}
public List<User> findAll() {
return userRepository.findAll();
}
public void addNewUser(User user) {
Optional<User> userOptional = userRepository.findUserByEmail(user.getEmail());
if(userOptional.isPresent()){
throw new IllegalStateException("email taken");
}
String hashedPassword = userConfig.passwordEncoder().encode(user.getPassword());
user.setPassword(hashedPassword);
userRepository.save(user);
}
public void loginUser(User user){
Optional<User> userOptional = userRepository.findUserByEmail(user.getEmail());
if(userOptional.isEmpty()){
throw new IllegalStateException("no account under that email");
}
else
if(!userConfig.passwordEncoder().matches(user.getPassword(),
userOptional.get().getPassword())){
throw new IllegalStateException("wrong password");
}
//!userOptional.get().getPassword().equals(user.getPassword())
}
}
Password encoder is a bean in class UserConfig.
#Configuration
public class UserConfig {
#Bean
CommandLineRunner commandLineRunnerUser(UserRepository repository) {
return args -> {
User iza = new User(
"iza#gmail.com",
"$2a$10$U87IFlm9DYXRITUSnfdfDuknz8ijJCcK9UVR4D4kUDu7w13zPuURK"
);
User andrzej = new User(
"andrzej#gmail.com",
"$2a$10$fmYOxyvWBr47wAg1m/ryy.G4J1PbT2LRj6m7oENkBtEsGocansE9G"
);
User tomek = new User(
"tomek#gmail.com",
"$2a$10$chrySvbZSZcje4r3Q0PZv.FrO6/k2WvM42GX3x2EmySZc/dAA2glC"
);
repository.saveAll(
List.of(iza,andrzej,tomek)
);
};
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Do i need to create another method with password encoder inside my test class? I don't know what am i doing wrong. Why does it say that result is null?
Does someone know what am i doing wrong?
In your UserServiceTest, you're currently mocking UserConfig. A mock is basically an implementation that has no behavior at all. This means that userConfig.passwordEncoder() will return null in your test.
To solve this, you have to tell Mockito what the behavior is of your UserConfig class. For example:
Mockito.when(userConfig.passwordEncoder()).thenReturn(new BCryptPasswordEncoder());
This also allows you to use a different (eg. a dummy) password encoder in your unit tests.
Another suggestion, unrelated to your question, is that you can directly autowire PasswordEncoder in your UserService in stead of autowiring UserConfig. This works because you annotated UserConfig with #Configuration and UserConfig.passwordEncoder() with #Bean:
#Service
public class UserService {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder; // Change this
// And change the constructor parameter
#Autowired
public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder) {
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder; // And this
}
// The rest of your code...
}
I couldn't use userRepo to saveUser properly, the mysql query showed wrong order of insertion, therefore not working. Here's my UserRepository:
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Integer> {
Optional<User> findUserByUsername(String username);
}
Here's my user service:
#Service
public class UserServiceImpl implements IUserService, UserDetailsService {
private Logger logger = LogManager.getLogger(UserServiceImpl.class);
#Autowired
private UserRepository userRepo;
#Autowired
private BCryptPasswordEncoder encoder;
//field name not in correct order, can not use it
#Override
public Integer saveUser(User user) {
String passwd = user.getPassword();
String encodedPasswod = encoder.encode(passwd);
logger.log(Level.ERROR, "passwd:" + encodedPasswod);
user.setPassword(encodedPasswod);
ArrayList<String> roles = new ArrayList<String>();
roles.add("Member");
user.setRoles(roles);
user = userRepo.save(user);
return user.getUserid();
}
public UserServiceImpl(UserRepository userRepository) {
this.userRepo = userRepository;
}
...
Someone can help? So frustrated with springboot.
M.
Look like you missing #Transactional on the saveUser method.
So I'm new to Unit Testing.
I'm trying to test the behavior of the method findAll() in IngredientServiceImplTest.
The problem that I'm facing has to do with the return value of the method mocked. It always return empty thus throwing the exception.
Can someone tell me what I'm missing?
Testing class.
#ExtendWith(MockitoExtension.class)
class IngredientServiceImplTest {
#Mock
private MenuItemIngredientRepository menuItemIngredientRepository;
#Mock
private IngredientRepository ingredientRepository;
#InjectMocks
private IngredientServiceImpl ingredientService;
#Mock
private JpaRepository<Ingredient, Long> jpaRepository;
#Mock
private BaseMapper<IngredientCreateDto, IngredientUpdateDto, IngredientResponseDto,
Ingredient> baseMapper;
#BeforeEach
void init() {
ingredientService.jpaRepository = jpaRepository;
ingredientService.baseMapper = baseMapper;
}
#Test
void When_FindById_ReturnIngredient() {
Ingredient ingredient = new Ingredient();
ingredient.setId(1L);
ingredient.setName("Name");
IngredientCreateDto ingredientCreateDto = new IngredientCreateDto();
ingredientCreateDto.setName("Name");
when(jpaRepository.findById(ingredient.getId())).thenReturn(Optional.of(ingredient));
when(baseMapper.createDtoToEntity(ingredientCreateDto)).thenReturn(ingredient);
assertEquals(ingredientService.findById(ingredient.getId()).getName(),
}
Base service class
#AllArgsConstructor
#NoArgsConstructor
public class BaseServiceImpl<CREATE_DTO, UPDATE_DTO, RESPONSE_DTO, ENTITY> implements BaseService<CREATE_DTO, UPDATE_DTO, RESPONSE_DTO, ENTITY> {
#Autowired
protected JpaRepository<ENTITY, Long> jpaRepository;
#Autowired
protected BaseMapper<CREATE_DTO, UPDATE_DTO, RESPONSE_DTO, ENTITY> baseMapper;
#Override
public List<RESPONSE_DTO> findAll() {
return jpaRepository.findAll()
.stream()
.map(baseMapper::entityToResponseDto)
.collect(Collectors.toList());
}
#Override
public RESPONSE_DTO findById(Long id) {
return jpaRepository.findById(id)
.map(baseMapper::entityToResponseDto)
.orElseThrow(() -> {
throw new RuntimeException("Entity with id: " + id + " does not exist!");
});
}
#Override
public RESPONSE_DTO save(CREATE_DTO entity) {
return baseMapper.entityToResponseDto(jpaRepository.save(baseMapper.createDtoToEntity(entity)));
}
}
Ingredient Service class
#Service
#AllArgsConstructor
#Validated
public class IngredientServiceImpl extends BaseServiceImpl<IngredientCreateDto, IngredientUpdateDto, IngredientResponseDto, Ingredient> implements IngredientService{
private final MenuItemIngredientRepository menuItemIngredientRepository;
private final IngredientRepository ingredientsRepository;
#Override
public IngredientResponseDto update(Long id, IngredientUpdateDto ingredient) {
super.findById(id);
Ingredient entityIngredient = baseMapper.updateDtoToEntity(ingredient);
entityIngredient.setId(id);
entityIngredient.setUpdatedAt(LocalDateTime.now());
return baseMapper.entityToResponseDto(jpaRepository.save(entityIngredient));
}
#Override
public List<IngredientResponseDto> findTopIngredients(Integer n) {
return menuItemIngredientRepository.findTopIngredients(n)
.stream()
.map(id -> baseMapper.entityToResponseDto(jpaRepository.getOne(id)))
.collect(Collectors.toList());
}
#Override
public List<IngredientResponseDto> findAllByFilter(IngredientFilter ingredientFilter) {
return ingredientsRepository.findAllByFilter(ingredientFilter)
.stream()
.map(ingredient -> baseMapper.entityToResponseDto(ingredient))
.collect(Collectors.toList());
}
}
This question already has answers here:
Spring Couldn't autowired,there is more than one bean of `` type
(5 answers)
Closed 2 years ago.
I am using IntelliJ Idea IDE to run the code but it shows Could not autowire. There is more than one bean of 'UserDetailsService' type. But the same code in the Eclipse IDE is running correctly.
It is the code about Spring Security. Please Help me to fix the bug in my code.
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Bean
public AuthenticationProvider authProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(userDetailsService());
provider.setPasswordEncoder(new BCryptPasswordEncoder());
return provider;
}
}
#Service
public class MyUserDetailsService implements UserDetailsService {
#Autowired
private UserRepository repo;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = repo.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("404");
}
return new UserPrincipals(user);
}
}
public class UserPrincipals implements UserDetails {
private User user;
public UserPrincipals(User user) {
this.user = user;
}
#Override
public Collection << ? extends GrantedAuthority > getAuthorities() {
return Collections.singleton(new SimpleGrantedAuthority("USERS"));
}
#Override
public String getPassword() {
return user.getPassword();
}
#Override
public String getUsername() {
return user.getUsername();
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
}
public interface UserRepository extends JpaRepository < User, Long > {
User findByUsername(String username);
}
Why IntelliJ Idea is showing this type of error is this error in my code or something else, help me
#Autowired
private UserDetailsService userDetailsService;
UserDetailsService has multiple implementations & beans (including MyUserDetailsService that you defined), therefore Spring doesn't know which one to inject in the above case.
You need to explicitly specify which bean to inject using #Qualifier. Like so:
#Qualifier("MyUserDetailsService")
private UserDetailsService userDetailsService
I have a few classes in the JPA Base made with the use of SpringData and SpringBoot. I would like to create a controller which shows the rest out of a few classes and not only one. Sadly, I can't find any examples.
This is my controller:
#RestController
#RequestMapping("/user")
public class UserController {
private final UserRepository userRepository;
#Autowired
public UserController(UserRepository userRepository) {
this.userRepository = userRepository;
}
#RequestMapping(method = RequestMethod.POST)//add
public void addUser(#RequestBody User user) {
userRepository.save(user);
}
#RequestMapping(method = RequestMethod.GET)
public List<User> getUser(){
return userRepository.findAll();
}
}