Mocked method always returns empty Optional - spring-boot

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());
}
}

Related

Test Result showing null while performing jUnit5 Test

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.

HazelcastRepository - how to save a new entity (with the id from sequence) and put it to the map

I would like to save a new entity using HazlecastRepository.
When the id is null, the KeyValueTemplate use SecureRandom and generate id which is like -123123123123123123.
I don't want to save id like that, instead of that i woud like to get it from sequence in db and put it to the map.
I have found 2 solutions:
1) In AdminService get the next value from sequence in database and set it
2) Create atomic counter id in the Hazelcast server and init it with the current value from the sequence. In AdminService get counter, increment value and set id.
but they are not very pretty.
Do you have any other ideas?
The code:
#Configuration
#EnableHazelcastRepositories(basePackages = "com.test")
public class HazelcastConfig {
#Bean
public HazelcastInstance hazelcastInstance(ClientConfig clientConfig) {
return HazelcastClient.newHazelcastClient(clientConfig);
}
#Bean
#Qualifier("client")
public ClientConfig clientConfig() {
ClientConfig clientConfig = new ClientConfig();
clientConfig.setClassLoader(HazelcastConfig.class.getClassLoader());
ClientNetworkConfig networkConfig = clientConfig.getNetworkConfig();
networkConfig.addAddress("127.0.0.1:5701");
networkConfig.setConnectionAttemptLimit(20);
return clientConfig;
}
#Bean
public KeyValueTemplate keyValueTemplate(ClientConfig clientConfig) {
return new KeyValueTemplate(new HazelcastKeyValueAdapter(hazelcastInstance(clientConfig)));
}
}
#Service
#RequiredArgsConstructor
public class AdminService {
private final UserRepository userRepository;
...
#Transactional
public User addOrUpdateUser(UserUpdateDto dto) {
validate(dto);
User user = dto.getId() != null ? userService.getUser(dto.getId()) : new User();
mapUser(user, dto);
return userRepository.save(user);
}
...
}
#Repository
public interface UserRepository extends HazelcastRepository<User, Long> {
}
#KeySpace("users")
#Entity
#Table(name = "users)
#Data
#AllArgsConstructor
#NoArgsConstructor
public class User extends DateAudit implements Serializable {
#javax.persistence.Id
#org.springframework.data.annotation.Id
// #GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_generator")
// #SequenceGenerator(name="user_generator", sequenceName = "user_seq")
private Long id;
...
}
Hazelcast server:
#Component
#Slf4j
public class UserLoader implements ApplicationContextAware, MapStore<Long, User> {
private static UserJpaRepository userJpaRepository;
#Override
public User load(Long key) {
log.info("load({})", key);
return userJpaRepository.findById(key).orElse(null);
}
#Override
public Map<Long, User> loadAll(Collection<Long> keys) {
Map<Long, User> result = new HashMap<>();
for (Long key : keys) {
User User = this.load(key);
if (User != null) {
result.put(key, User);
}
}
return result;
}
#Override
public Iterable<Long> loadAllKeys() {
return userJpaRepository.findAllId();
}
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
userJpaRepository = applicationContext.getBean(UserJpaRepository.class);
}
#Override
public void store(Long aLong, User user) {
userJpaRepository.save(user);
}
#Override
public void storeAll(Map<Long, User> map) {
for (Map.Entry<Long, User> mapEntry : map.entrySet()) {
store(mapEntry.getKey(), mapEntry.getValue());
}
}
#Override
public void delete(Long aLong) {
userJpaRepository.deleteById(aLong);
}
#Override
public void deleteAll(Collection<Long> collection) {
collection.forEach(this::delete);
}
}
public interface UserJpaRepository extends CrudRepository<User, Long> {
#Query("SELECT u.id FROM User u")
Iterable<Long> findAllId();
}
I think that there is no better way than what you described.
I'd go with the second solution, because then you're at least coupled to Hazelcast server only.

Tables not created in Cassandra db using springboot

I tried to create tables in cassandra db on start-up of spring boot application but it doesn't seem to be able to create tables. Below is my configuration. I have the #EnableCassandraRepositories in my Application class. I already created my keyspace by default. So its just the tables that I'm looking to create.
Configuration
#Configuration
public class CassandraConfig extends AbstractCassandraConfiguration {
#Value("${cassandra.contactpoints}")
private String contactPoints;
#Value("${cassandra.port}")
private int port;
#Value("${cassandra.keyspace}")
private String keySpace;
#Value("${cassandra.basePackages}")
private String basePackages;
#Autowired
private Environment environment;
#Override
protected String getKeyspaceName() {
return keySpace;
}
#Override
#Bean
public CassandraClusterFactoryBean cluster() {
final CassandraClusterFactoryBean cluster = new CassandraClusterFactoryBean();
cluster.setContactPoints(contactPoints);
cluster.setPort(port);
return cluster;
}
#Override
#Bean
public CassandraMappingContext cassandraMapping() throws ClassNotFoundException {
return new BasicCassandraMappingContext();
}
}
Entity
#Table
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
public class AssessmentAttemptDetailsEntity implements Serializable {
#PrimaryKeyColumn(type = PrimaryKeyType.PARTITIONED)
private String assessmentId;
#PrimaryKeyColumn(type = PrimaryKeyType.CLUSTERED)
private String attempid;
}
Application
#SpringBootApplication
#ComponentScan(basePackages = {"com.lte.assessmentanalytics.service","com.lte.assessmentanalytics.config", "com.lte.assessmentanalytics.model", "com.lte.assessmentanalytics.listener"})
#EnableCassandraRepositories("com.lte.assessmentanalytics.model")
public class AssessmentanalyticsApplication {
#Autowired
private AssessmentAttemptRepository assessmentAttemptRepository;
public static void main(String[] args) {
SpringApplication.run(AssessmentanalyticsApplication.class, args);
}
}
Repository
#Repository
public interface AssessmentAttemptRepository extends CassandraRepository<AssessmentAttemptDetailsEntity, Long> {
}
I was able to fix this by modifying my CassandraConfig class to.
#Configuration
#EnableCassandraRepositories("com.lte.assessmentanalytics.model")
public class CassandraConfig extends AbstractCassandraConfiguration {
#Value("${cassandra.contactpoints}")
private String contactPoints;
#Value("${cassandra.port}")
private int port;
#Value("${cassandra.keyspace}")
private String keySpace;
#Value("${cassandra.basePackages}")
private String basePackages;
#Override
protected String getKeyspaceName() {
return keySpace;
}
#Override
protected String getContactPoints() {
return contactPoints;
}
#Override
protected int getPort() {
return port;
}
#Override
public SchemaAction getSchemaAction() {
return SchemaAction.CREATE_IF_NOT_EXISTS;
}
#Override
public String[] getEntityBasePackages() {
return new String[] {basePackages};
}
}

JUNIT - Null pointer Exception while calling findAll in spring Data JPA

I am new to Junits and Mockito, I am writing a Unit test class to test my service class CourseService.java which is calling findAll() method of CourseRepository.class which implements CrudRepository<Topics,Long>
Service Class
#Service
public class CourseService {
#Autowired
CourseRepository courseRepository;
public void setCourseRepository(CourseRepository courseRepository) {
this.courseRepository = courseRepository;
}
public Boolean getAllTopics() {
ArrayList<Topics> topicList=(ArrayList<Topics>) courseRepository.findAll();
if(topicList.isEmpty())
{
return false;
}
return true;
}
}
Repository class
public interface CourseRepository extends CrudRepository<Topics,Long>{
}
Domain class
#Entity
#Table(name="Book")
public class Topics {
#Id
#Column(name="Topicid")
private long topicId;
#Column(name="Topictitle",nullable=false)
private String topicTitle;
#Column(name="Topicauthor",nullable=false)
private String topicAuthor;
public long getTopicId() {
return topicId;
}
public void setTopicId(long topicId) {
this.topicId = topicId;
}
public String getTopicTitle() {
return topicTitle;
}
public void setTopicTitle(String topicTitle) {
this.topicTitle = topicTitle;
}
public String getTopicAuthor() {
return topicAuthor;
}
public void setTopicAuthor(String topicAuthor) {
this.topicAuthor = topicAuthor;
}
public Topics(long topicId, String topicTitle, String topicAuthor) {
super();
this.topicId = topicId;
this.topicTitle = topicTitle;
this.topicAuthor = topicAuthor;
}
}
Following is the Junit class I have written but courseRepository is getting initialized to NULL and hence I am getting NullPointerException.
public class CourseServiceTest {
#Mock
private CourseRepository courseRepository;
#InjectMocks
private CourseService courseService;
Topics topics;
#Mock
private Iterable<Topics> topicsList;
#Before
public void setUp() {
MockitoAnnotations.initMocks(CourseServiceTest.class);
}
#Test
public void test_Get_Topic_Details() {
List<Topics> topics = new ArrayList<Topics>();
Mockito.when(courseRepository.findAll()).thenReturn(topics);
boolean result=courseService.getAllTopics();
assertTrue(result);
}
}
Change the setUp() method to:
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
Probably you are dealing with some problem on the framework to make the mocked class be injected by the framework.
I recommend to use Constructor Injection, so you don't need to rely on the reflection and #Inject/#Mock annotations to make this work:
#Service
public class CourseService {
private final CourseRepository courseRepository;
// #Autowired annotation is optional when using constructor injection
CourseService (CourseRepository courseRepository) {
this.courseRepository = courseRepository;
}
// .... code
}
The test:
#Test
public void test_Get_Topic_Details() {
List<Topics> topics = new ArrayList<Topics>();
Mockito.when(courseRepository.findAll()).thenReturn(topics);
CourseService courseService = new CourseService(courseRepository);
boolean result = courseService.getAllTopics();
assertTrue(result);
}

QueryDslMongoRepository for different collections

I am trying to implement a QueryDslMongoRepository for a model "Document"
#QueryEntity
#Document(collection="currentDocuments")
public class DocumentImpl extends TranslatableObjectImpl implements Document
In our current implementation a to be deleted document moves von "currentDocuments" into "deletedDocuments" collection.
I cant find a solution to create a repository like this
public interface DocumentRepository extends MongoRepository<DocumentImpl, String> ,QueryDslPredicateExecutor<DocumentImpl> {}
with a dynamic collection name.
My goal is to have the advantages of queryDsl in one Repository for different collections and to be able to move models from one collection into another like
public move(DocumentImpl entity, String sourceCollection, String targetCollection){
repository.delete(entity,sourceCollection);
repository.save(entity,targetCollection);
}
or something like
public List<Document> findAllDocumentsWithAttachments(String collectionName){
return repository.findAll(QDocumentImpl.documentImpl.attachments.isNotEmpty(), collectionName);
}
Any suggestions?
I implemented this feature by creating an own FactoryBean extending MongoRepositoryFactoryBean.
According to the Answer of this -> Question <- I implemeted following solution.
Entity
#QueryEntity
public class Document extends AbstractObject {
}
Custom QuerydslMongoRepository
public interface CustomQuerydslMongoRepository<T extends AbstractObject,ID extends Serializable> extends MongoRepository<T, ID> ,QueryDslPredicateExecutor<T>{
List<T> findAll(Predicate predicate, String collectionName);
T save(T entity, String collectionName);
...
}
Custom QuerydslMongoRepository Implementation
public class CustomQuerydslMongoRepositoryImpl<T extends AbstractObject,ID extends Serializable> extends QueryDslMongoRepository<T,ID> implements CustomQuerydslMongoRepository<T,ID> {
//All instance variables are available in super, but they are private
private static final EntityPathResolver DEFAULT_ENTITY_PATH_RESOLVER = SimpleEntityPathResolver.INSTANCE;
private final EntityPath<T> path;
private final PathBuilder<T> pathBuilder;
private final MongoOperations mongoOperations;
public CustomQuerydslMongoRepositoryImpl(MongoEntityInformation<T, ID> entityInformation, MongoOperations mongoOperations) {
this(entityInformation, mongoOperations,DEFAULT_ENTITY_PATH_RESOLVER);
}
public CustomQuerydslMongoRepositoryImpl(MongoEntityInformation<T, ID> entityInformation, MongoOperations mongoOperations, EntityPathResolver resolver) {
super(entityInformation, mongoOperations, resolver);
this.path=resolver.createPath(entityInformation.getJavaType());
this.pathBuilder = new PathBuilder<T>(path.getType(), path.getMetadata());
this.mongoOperations=mongoOperations;
}
#Override
public List<T> findAll(Predicate predicate, String collectionName) {
MongodbQuery<T> query = createQueryFor(predicate,collectionName);
return query.list();
}
#Override
public T save(T entity,String collectionName){
Assert.notNull(entity, "Entity must not be null!");
mongoOperations.save(entity, collectionName);
return entity;
}
private MongodbQuery<T> createQueryFor(Predicate predicate,String collectionName) {
Class<T> domainType = getEntityInformation().getJavaType();
MongodbQuery<T> query = new SpringDataMongodbQuery<T>(getMongoOperations(), domainType,collectionName);
return query.where(predicate);
}
}
Custom Repository Factory
public class CustomQueryDslMongodbRepositoryFactoryBean<R extends QueryDslMongoRepository<T, I>, T, I extends Serializable> extends MongoRepositoryFactoryBean<R, T, I> {
#Override
protected RepositoryFactorySupport getFactoryInstance(MongoOperations operations) {
return new CustomQueryDslMongodbRepositoryFactory<T,I>(operations);
}
public static class CustomQueryDslMongodbRepositoryFactory<T, I extends Serializable> extends MongoRepositoryFactory {
private MongoOperations operations;
public CustomQueryDslMongodbRepositoryFactory(MongoOperations mongoOperations) {
super(mongoOperations);
this.operations = mongoOperations;
}
#SuppressWarnings({ "rawtypes", "unchecked" })
protected Object getTargetRepository(RepositoryMetadata metadata) {
return new CustomQuerydslMongoRepositoryImpl(getEntityInformation(metadata.getDomainType()), operations);
}
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
return CustomQuerydslMongoRepository.class;
}
}
}
Entity Repository
public interface DocumentRepository extends CustomQuerydslMongoRepository<Document, String>{
}
Usage in Service
#Autowired
DocumentRepository repository;
public List<Document> getAllDocuments(Predicate predicate){
return repository.findAll(predicate,"myCustomCollection");
}

Resources