Search code examples
javaunit-testingjpaspring-data-jpaentitymanager

Jpa unit test - Service - entity manager null


This is what I tried:

@RunWith(SpringRunner.class)
@DataJpaTest
@ActiveProfiles("h2")
@Rollback(false)
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class ServiceTest {

    private EntityManager entityManager;

    public ServiceTest(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    @Test
    public void findLocation() {

        Location location  = entityManager.find(Location.class, 2);

        assertEquals(location.getName(), "Avenue");
    }
    @Test
    public void updateLocation() {

        Location location = entityManager.find(Location.class, 2);
        location.setNo_people(10);
        entityManager.persist(location);
        entityManager.flush();
    }
    
}

the error that I get is ' Runner org.junit.internal.runners.ErrorReportingRunner (used on class com.unibuc.AWBD_Project_v1.services.ServiceTest) does not support filtering and will therefore be run completely. Test class should have exactly one public zero-argument constructor'

Here is the LocationService:

@Service
public class LocationService implements BaseService<Location> {
    private final LocationRepository locationRepository;

    @Autowired
    public LocationService(com.unibuc.AWBD_Project_v1.repositories.LocationRepository locationRepository) {
        this.locationRepository = locationRepository;
    }

    @Override
    public Location insert(Location object) {
        return locationRepository.save(object);
    }

    @Override
    public Location update(Long id, Location updatedObject) {
        var foundId =  locationRepository.findById(id);

        return foundId.map(locationRepository::save).orElse(null);
    }

    @Override
    public List<Location> getAll() {
        return locationRepository.findAll();
    }

    @Override
    public Optional<Location> getById(Long id) {
        return locationRepository.findById(id);
    }

    @Override
    public void deleteById(Long id)
    {
        try {
            locationRepository.deleteById(id);
        } catch (LocationException e) {
            throw  new LocationException("Location not found");
        }
    }

    @Override
    public Page<Location> findAll(int page, int size, String sortBy, String sortType){
        Sort sort = sortType.equalsIgnoreCase(Sort.Direction.ASC.name()) ? Sort.by(sortBy).ascending() :
                Sort.by(sortBy).descending();
        Pageable pageable = PageRequest.of(page - 1, size, sort);
        return  locationRepository.findAll(pageable);
    }

}

Solution

  • Hello there is 3 issues in your test code.

    1 you should remove the EntityManager entityManager from your test constructor to have a runnable test class.

    2 if you want to use entityManager inside your test class you should @Autowired it

    public class ServiceTest {
        @Autowired
        private EntityManager entityManager;
    

    3 It's look like you are testing entityManager and not your LocationService In an unit test you should mock dependencies like entityManager using Mockito

    It's seems like you wanted to create an integration test.

    The 3 steps of one integration test of a service (exemple with findLocation())

    1. Prepare the data inside a test database Create a new location object and save it into database using the entityManager or the testEntityManager.

    2. Execute your findLocation methode on the id Don't forget to Autowire your service class.

    3. Verify if the retrieved data is as expected Compare the retrieved Location object with the one you've saved.

    Here's the code

    @RunWith(SpringRunner.class)
    @DataJpaTest
    @ActiveProfiles("h2")
    @Rollback(false)
    @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
    public class ServiceTest {
        @Autowired
        private EntityManager entityManager;
        @Autowired  
        private LocationService locationService;
    
        public ServiceTest() {
            
        }
    
        @Test
        public void findLocation() {
            //given
    
            Location location  = new Location(....);
            entityManager.save(location);
    
            //when
            Location foundLocation=locationService.getById(location.getId());
            //then
            assertTrue(foundLocation.isPresent());
            assertEquals(foundLocation.get().getName(), "Avenue");
        }
    

    If you have any question I'm available to help you.