I have tried the following steps but no luck sadly :
Method number 1 always fail because size expected 1 but its 2 -> test runned individually passing through successfully but when i run all application tests then exactly that one is failing
1)Mark each method with #DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD)
2)Mark at class level #DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
3)Mark methods with #Transactional
#SpringBootTest
public class ExportServiceTest {
#Autowired
ExportService exportService;
#Autowired
ExportRepository exportRepository;
#Autowired
UserRepository userRepository;
#Test
public void onlyOneExportUserShouldBeAddedWithMultipleEntries() {
UserEntity userEntity = new UserEntity().setId(2L);
exportService.createIfNotExist(userEntity);
exportService.createIfNotExist(userEntity);
Assertions.assertThat(exportRepository.findAll()).hasSize(1);
}
#Test
public void exportUserShouldBeAdded() {
UserEntity userEntity = new UserEntity().setId(1L);
exportService.createIfNotExist(userEntity);
Optional<UserExportEntity> exportUser = exportRepository.findByUserEntityId(userEntity.getId());
Assertions.assertThat(exportUser).isPresent();
}
#Test
public void shouldHaveTwoRecordsInExport() {
UserEntity userEntity = new UserEntity().setId(1L).setEmail("test#test.com");
UserEntity userEntity2 = new UserEntity().setId(2L).setEmail("test1#test.com");
userRepository.save(userEntity);
userRepository.save(userEntity2);
exportService.createIfNotExist(userEntity2);
exportService.createIfNotExist(userEntity);
Assertions.assertThat(exportRepository.findAll()).hasSize(2);
}
}
Related
This is my repository class:
#Repository
public interface EntitlementRepository extends JpaRepository<Entitlement, Long> {
Entitlement findByIdAndActiveTrue(Long entitlementId);
List<Entitlement> findByIdInAndActiveTrue(Collection<Long> entitlementIds);
List<Entitlement> findByIdIn(Collection<Long> entitlementIds);
#Modifying
#Query(value = "UPDATE ENTITLEMENT set RESTRICTION_LEVEL=:restrictionLevel where ID =:entitlementId", nativeQuery = true)
void updateRestrictionLevel(#Param("restrictionLevel") String restrictionLevel, #Param("entitlementId") Long entitlementId);
}
This is my repository class junit:
#RunWith(SpringRunner.class)
#DataJpaTest
#ActiveProfiles("test")
public class EntitlementRepositoryTest {
#Autowired
private TestEntityManager entityManager;
#Autowired
private EntitlementRepository repository;
#Test
public void testUpdate() {
Entitlement entitlementToAdd = anEntitlement("APPROVER1", "APPROVER2", "APPROVER3", null);
Entitlement savedEnt = repository.save(entitlementToAdd); // create Entitlement with restriction null
repository.updateRestrictionLevel("LEVEL11", savedEnt.getId()); // update restriction level
Entitlement updatedEnt = repository.findByIdAndActiveTrue(savedEnt.getId());
assertThat(updatedEnt.getRestrictionLevel()).isEqualTo("LEVEL11");
}
}
The restrictionLevel doesn't get updated. It stays null. Hence, assert statement fails.
This is similar to How to test method from repository which marked as #Modifying?
Solved the problem by adding a entityManager.clear();
#RunWith(SpringRunner.class)
#DataJpaTest
#ActiveProfiles("test")
public class EntitlementRepositoryTest {
#Autowired
private TestEntityManager entityManager;
#Autowired
private EntitlementRepository repository;
#Test
public void testUpdate() {
Entitlement entitlementToAdd = anEntitlement("APPROVER1", "APPROVER2", "APPROVER3", null);
Entitlement savedEnt = repository.save(entitlementToAdd); // create Entitlement with restriction null
repository.updateRestrictionLevel("LEVEL11", savedEnt.getId()); // update restriction level
entityManager.clear();
Entitlement updatedEnt = repository.findByIdAndActiveTrue(savedEnt.getId());
assertThat(updatedEnt.getRestrictionLevel()).isEqualTo("LEVEL11");
}
}
public class UserService {
#Autowired
private UserRepository userRepository;
#Autowired
private ConverterService converterService;
public User addUser(UserDto userdto) {
User convertedUser = converterService.convertToEntity(userdto);
convertedUser.setUserId(userdto.getUserId());
convertedUser.setUserName(userdto.getUserName());
User savedUser = userRepository.save(convertedUser);
return savedUser;
}
}
//while debugging userRepository.save(convertedUser) method, it always returning null.
Below is my UserServiceTest.java class
#RunWith(SpringRunner.class)
#SpringBootTest
public class UserServiceTest {
#Autowired
private UserService userService;
#Mock
private ConverterService converterService;
#MockBean
private UserRepository userRepository;
#Test
public void addUserTest() {
UserDto userDto = new UserDto();
userDto.setUserId("123");
userDto.setUserName("AB");
User user = new User("123","ABC");
Mockito.when(converterService.convertToEntity(new UserDto())).thenReturn(user);
Mockito.when(userRepository.save(user)).thenReturn(user);
User user1 = userService.addUser(userDto);
Assert.assertEquals(user,userService.addUser(userDto));
}
}
userService.addUser(userDto) this method is always return by null from service class. because of below condition is failing : Assert.assertEquals(user,userService.addUser(userDto));
you shouldn't pass null value to the assertEquals method. But you can do like this;
Assert.assertEquals(Objects.equals(user,userService.addUser(userDto)),true);
I am working on the Spring Boot web app and I have a custom realization of the ModelMapper library that allows me to convert single objects and a list of objects.
#Component
public class ObjectMapperUtils {
#Autowired
private static ModelMapper modelMapper;
static {
modelMapper = new ModelMapper();
modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
}
private ObjectMapperUtils() {
}
public <D, T> D map(final T entity, Class<D> outClass) {
return modelMapper.map(entity, outClass);
}
public <D, T> List<D> mapAll(final Collection<T> entityList, Class<D> outCLass) {
return entityList.stream().map(entity -> map(entity, outCLass)).collect(Collectors.toList());
}
}
On the Service layer, I have a method returns from DB UserEntity object and convert it to UserDTO.
#Autowired
private UserRepository userRepository;
#Autowired
private ObjectMapperUtils modelMapper;
#Override
public UserDTO getByUserId(String userId) {
UserEntity userEntity = userRepository.findByUserId(userId)
.orElseThrow(() -> new NotFoundException("User with userId[" + userId + "] not found"));
//UserDTO userDTO = new UserDTO();
//BeanUtils.copyProperties(userEntity, userDTO);
return modelMapper.map(userEntity, UserDTO.class); // userDTO;
}
The problem occurs when I try to create a test for this method. UserDTO always returned as NULL value.
class UserServiceImplTest {
#InjectMocks
private UserServiceImpl userService;
#Mock
private UserRepository userRepository;
#Mock
private ObjectMapperUtils modelMapper;
#BeforeEach
void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
void testGetByUserId() {
UserEntity userEntity = new UserEntity();
userEntity.setId(1L);
userEntity.setUsername("zavada");
userEntity.setUserId("33b4c069-e907-45a9-8d49-2042044c56e0");
when(userRepository.findByUserId(anyString()))
.thenReturn(Optional.of(userEntity));
UserDTO userDTO = userService.getByUserId("33b4c069-e907-45a9-8d49-2042044c56e0");
System.out.println(userDTO); <--- NULL
assertEquals("zavada", userDTO.getUsername());
assertNotNull(userDTO);
}
}
When I use on the Service layer converting by BeanUtils.copyProperties(obj1, obj2); - the test is passed successfully. With ModelMapper I get NULL. Any ideas how to solve this error or refactor code? Thanks in advance
To build upon user268396 answer you would need the following to get this to work:
#RunWith(MockitoJUnitRunner.class)
public class StackOverflowTest {
#InjectMocks
private StackOverflow userService = new StackOverflow();
#Mock
private UserRepository userRepository;
#Mock
private ObjectMapperUtils modelMapper;
private UserDTO userDTO = new UserDTO();
private UserEntity userEntity = new UserEntity();
#Before
public void setUp() {
when(modelMapper.map(any(), any())).thenReturn(userDTO);
userDTO.setId(1L);
userDTO.setUsername("zavada");
userDTO.setUserId("33b4c069-e907-45a9-8d49-2042044c56e0");
}
#Test
public void testGetByUserId() throws Throwable {
when(userRepository.findByUserId(anyString())).thenReturn(Optional.of(userEntity));
UserDTO result = userService.getByUserId("33b4c069-e907-45a9-8d49-2042044c56e0");
System.out.println(result);
assertEquals("zavada", result.getUsername());
assertNotNull(result);
}
}
This is quite an easy mistake to make, it is important to remember that all you #mocked objects are not real implementations anymore and if you expect any behaviour back you would need to define it upfront.
If you have a #Mock private ObjectMapperUtils modelMapper; then by default you do not have a real ObjectMapperUtils. So you are not calling your implementation, you are calling the default stubs that Mockito provides for you. That is why you are getting a null return value from modelMapper.map().
Either do not mock the ObjectMapperUtils bean or arrange for it to do something suitable using when() etc. from the Mockito API.
For the same situation, you could also do
Do not mock the ObjectMapperUtils class in your test class.
In the #Before init() ..{} method instantiate your UserServiceImpl to new instance of ObjectMapperUtils. And then set it in the UserServiceImpl. i.e ,
userServiceImpl.setMapper(UserServiceImpl).
So your setup method will look something like this ,
#InjectMocks
private UserServiceImple userServiceImpl;
#Mock
private UserRepository userRepository;
private ObjectMapperUtil objectMapperUitl; // not mocked
#BeforeEach
public void init() {
objectMapperUitls = new ObjectMapperUtils();
userServiceImple.setMapper(objectMapperUitls);
}
I'm quite a newbie to Spring boot, but here's the problem I'm facing now:
// Application.java
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Autowired
private Cluster cluster = null;
#PostConstruct
private void migrateCassandra() {
Database database = new Database(this.cluster, "foo");
MigrationTask migration = new MigrationTask(database, new MigrationRepository());
migration.migrate();
}
}
So basically, I'm trying to bootstrap a spring application, and after that, do some cassandra migrations.
I also have defined a repository for my user model:
// UserRepo.java
public interface UserRepo extends CassandraRepository<User> {
}
Now I'm trying to test my repo class using the following simple test case:
// UserRepoTest.java
#RunWith(SpringRunner.class)
#AutoConfigureTestDatabase(replace = Replace.NONE)
#DataJpaTest
public class UserRepoTest {
#Autowired
private UserRepo userRepo = null;
#Autowired
private TestEntityManager entityManager = null;
#Test
public void findOne_whenUserExists_thenReturnUser() {
String id = UUID.randomUUID().toString();
User user = new User();
user.setId(id);
this.entityManager.persist(user);
assertEquals(this.userRepo.findOne(user.getId()).getId(), id);
}
#Test
public void findOne_whenUserNotExists_thenReturnNull() {
assertNull(this.userRepo.findOne(UUID.randomUUID().toString()));
}
}
I would expect the test to pass, but instead, I got an error saying "No qualifying bean of type 'com.datastax.driver.core.Cluster' available". It looks like spring failed to autowire the cluster object, but why is that? How do I fix this? Thanks a lot!
The test environment needs to know where your beans are defined, so you have to tell it the location.
In your test class, add the #ContextConfiguration annotation:
#RunWith(SpringRunner.class)
#AutoConfigureTestDatabase(replace = Replace.NONE)
#DataJpaTest
#ContextConfiguration(classes = {YourBeans.class, MoreOfYourBeans.class})
public class UserRepoTest {
#Autowired
private UserRepo userRepo = null;
#Autowired
private TestEntityManager entityManager = null;
I'am trying to do a simple Integration test using Spring Boot Test in order to test the e2e use case. My test does not work because I'am not able to make the repository saving data, I think I have a problem with spring contexts ...
This is my Entity:
#Entity
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
public class Person {
#Id
private int id;
private String name;
}
This is the Person repository:
#Repository
public interface PersonRepository extends JpaRepository<Person, Integer> {
}
The Person service:
#Service
public class PersonService {
#Autowired
private PersonRepository repository;
public Person createPerson(int id,String name) {
return repository.save(new Person(id, name));
}
public List<Person> getPersons() {
return repository.findAll();
}
}
The Person Controller:
#RequestMapping
#RestController
public class PersonController {
#Autowired
private PersonService personService;
#RequestMapping("/persons")
public List<Person> getPersons() {
return personService.getPersons();
}
}
The main Application class:
#SpringBootApplication
public class BootIntegrationTestApplication {
public static void main(String[] args) {
SpringApplication.run(BootIntegrationTestApplication.class, args);
}
}
The application.properties file:
spring.datasource.url= jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=password
spring.jpa.hibernate.ddl-auto=create
spring.jpa.show-sql=true
And the Test:
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class BootIntegrationTestApplicationTests {
#Autowired
private PersonService personService;
#Autowired
private TestRestTemplate restTemplate;
#Test
#Transactional
public void contextLoads() {
Person person = personService.createPerson(1, "person1");
Assert.assertNotNull(person);
ResponseEntity<Person[]> persons = restTemplate.getForEntity("/persons", Person[].class);
}
}
The test does not work, because the service is not saving the Person entity ....
Thanks in advance
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
public class SmokeTest {
#Autowired
UserController userController;
#Autowired
UserDao userDAO;
#Rollback(false) // This is key to avoid rollback.
#Test
public void contextLoads() throws Exception {
System.out.println("Hiren");
System.out.println("started");
userDAO.save(new User("tyx", "x#x.com"));
}
}
Refer #Rollback(false) is key to avoid rollback.
Thanks to M. Deinum, I think I get the point,
So the best is to separate the logic of the test into two tests, the first will testing just the service (so this one could be transactional) and the second the controller:
Test 1:
#Test
#Transactional
public void testServiceSaveAndRead() {
personService.createPerson(1, "person1");
Assert.assertTrue(personService.getPersons().size() == 1);
}
Test 2:
#MockBean
private PersonService personService;
#Before
public void setUp() {
//mock the service
given(personService.getPersons())
.willReturn(Collections.singletonList(new Person(1, "p1")));
}
#Test
public void testController() {
ResponseEntity<Person[]> persons = restTemplate.getForEntity("/persons", Person[].class);
Assert.assertTrue(persons.getBody()!=null && persons.getBody().length == 1);
}
Spring for saving entity requires transaction. But until transaction has been commited changes not be visible from another transaction.
Simplest way is call controller after commit transaction
#Test
#Transactional
public void contextLoads() {
Person person = personService.createPerson(1, "person1");
Assert.assertNotNull(person);
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
#Override
public void afterCommit() {
ResponseEntity<Person[]> persons = restTemplate.getForEntity("/persons", Person[].class);
}
});
}
For each #Test function that makes a DB transaction, if you want to permanently persist the changes, then you can use #Rollback(false)
#Rollback(false)
#Test
public void createPerson() throws Exception {
int databaseSizeBeforeCreate = personRepository.findAll().size();
// Create the Person
restPersonMockMvc.perform(post("/api/people")
.contentType(TestUtil.APPLICATION_JSON_UTF8)
.content(TestUtil.convertObjectToJsonBytes(person)))
.andExpect(status().isCreated());
// Validate the Person in the database
List<Person> personList = personRepository.findAll();
assertThat(personList).hasSize(databaseSizeBeforeCreate + 1);
Person testPerson = personList.get(personList.size() - 1);
assertThat(testPerson.getFirstName()).isEqualTo(DEFAULT_FIRST_NAME);
assertThat(testPerson.getLastName()).isEqualTo(DEFAULT_LAST_NAME);
assertThat(testPerson.getAge()).isEqualTo(DEFAULT_AGE);
assertThat(testPerson.getCity()).isEqualTo(DEFAULT_CITY);
}
I tested it with a SpringBoot project generated by jHipster:
SpringBoot: 1.5.4
jUnit 4.12
Spring 4.3.9
Pay your attention to the order in which the tests are executed, the tests with the #Commit or #Rollback(false) annotation must be executed first: https://www.baeldung.com/junit-5-test-order
Do not use #Rollback(false). Unit Test should not generate data.
JPA FlushMode is AUTO (default - flush INSERT/UPDATE/DELETE SQL when query occurs) / COMMIT.
Just query the working entity for forcing FLUSH, or using EntityManager to force flush
#Test
public void testCreate(){
InvoiceRange range = service.createInvoiceRange(1, InvoiceRangeCreate.builder()
.form("01GTKT0/010")
.serial("NV/18E")
.effectiveDate(LocalDate.now())
.rangeFrom(1L)
.rangeTo(1000L)
.build(), new byte[] {1,2,3,4,5});
service.findByCriteria(1, "01GTKT0/010", "NV/18E"); // force flush
// em.flush(); // another way is using entityManager for force flush
}