jeudi 8 août 2019

In-memory database, for integration tests, loses all data after calling RestTemplate method

I am trying to write some tests for REST api but my in-memory database seems to drop all its data after I call any endpoint using RestTemplate. Before sending any requests, data is in the database but when @RestController is called then data is lost.

Test file:

@RunWith(SpringRunner.class)
@ActiveProfiles("test")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class EventServiceTests {

    @LocalServerPort
    private int randomServerPort;

    //@Autowired stuff

    @Test
    @Transactional
    public void createTest() {
        String createUrl = "http://localhost:" + randomServerPort + "/api/event";
        EventComponents eventComponents = eventUtils.getEventComponents();

        EventDto eventDto = new EventDto(
                "testEvent",
                eventComponents.getAddressDto(),
                eventComponents.getCategoryDto(),
                eventComponents.getSubcategoryDto(),
                eventComponents.getPerformerDtos(),
                new Date(),
                new Date()
        );
        RestTemplate createTemplate = new RestTemplate();
        addressDao.findAll().forEach(e-> System.out.println("foobar")); 
        // at this point there are some records in database
        CreateEventResponse response = createTemplate.postForObject(createUrl, eventDto, CreateEventResponse.class);
        //assertions
    }
}

Rest controller

@RestController
@RequestMapping("/api")
public class EventController {
    private EventProcess eventProcess;

    @Autowired
    private AddressDao addressDao; //for checking if data is in database

    public EventController(EventProcess eventProcess) {
        this.eventProcess = eventProcess;
    }

    @RequestMapping(value = "/event", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    public CreateEventResponse create(@RequestBody EventDto eventDto) {
        //at this point there is nothing, but should be some records
        System.out.println(addressDao.findAll().iterator().hasNext());
        return this.eventProcess.create(eventDto);
    }
}

I am really confused by this because at first I wrote really terrible piece of code but It passed all assertions. After a little bit of refactoring it stopped working but I only moved some logic elsewhere to improve readability.

Test file before refactoring (passes)

@RunWith(SpringRunner.class)
@ActiveProfiles("test")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class EventServiceTests {

    @LocalServerPort
    private int randomServerPort;

    private static final ArrayList<PerformerDto> performerDtos = new ArrayList<>();
    private static final ArrayList<CategoryDto> categoryDtos = new ArrayList<>();
    private static final ArrayList<SubcategoryDto> subcategoryDtos = new ArrayList<>();
    private static final ArrayList<CityDto> cityDtos = new ArrayList<>();
    private static final ArrayList<CountryDto> countryDtos = new ArrayList<>();
    private static final ArrayList<LocationCategoryDto> locationCategoryDtos = new ArrayList<>();
    private static final ArrayList<LocationDto> locationDtos = new ArrayList<>();
    private static final ArrayList<AddressDto> addressDtos = new ArrayList<>();

    //@Autowired stuff

    @BeforeClass
    public static void prepareData() {
        performerDtos.add(new PerformerDto("a"));
        performerDtos.add(new PerformerDto("ab"));
        performerDtos.add(new PerformerDto("abc"));
        performerDtos.add(new PerformerDto("abcd"));
        performerDtos.add(new PerformerDto("abcde"));

        categoryDtos.add(new CategoryDto("Music"));
        categoryDtos.add(new CategoryDto("Sport"));

        subcategoryDtos.add(new SubcategoryDto("Concert"));
        subcategoryDtos.add(new SubcategoryDto("Festival"));
        subcategoryDtos.add(new SubcategoryDto("Football"));
        subcategoryDtos.add(new SubcategoryDto("Basketball"));

        cityDtos.add(new CityDto("Warsaw"));
        cityDtos.add(new CityDto("Wroclaw"));

        countryDtos.add(new CountryDto("Poland"));
        countryDtos.add(new CountryDto("Russia"));

        locationCategoryDtos.add(new LocationCategoryDto(LocationType.INDOOR));
        locationCategoryDtos.add(new LocationCategoryDto(LocationType.OUTDOOR));

        locationDtos.add(new LocationDto(locationCategoryDtos.get(0), countryDtos.get(0), cityDtos.get(0)));
        locationDtos.add(new LocationDto(locationCategoryDtos.get(1), countryDtos.get(0), cityDtos.get(1)));

        addressDtos.add(new AddressDto("Test street 32A", "12", locationDtos.get(0)));
        addressDtos.add(new AddressDto("Klonowa 50", null, locationDtos.get(1)));
    }

    @Before
    @Transactional
    public void ensureData() {
        ensurePerformers();
        ensureCategories();
        ensureSubcategories();
        ensureAddress();
    }

    @Transactional
    public void ensurePerformers() {
        performerDtos.forEach(performerDto -> {
            if (performerDao.findByName(performerDto.getName()) == null)
                performerDao.save(new Performer(performerDto));
        });
    }

    @Transactional
    public void ensureCategories() {
        categoryDtos.forEach(categoryDto -> {
            if (categoryDao.findByName(categoryDto.getName()) == null)
                categoryDao.save(new Category(categoryDto));
        });
    }

    @Transactional
    public void ensureSubcategories() {
        subcategoryDtos.forEach(subcategoryDto -> {
            if (subcategoryDao.findByName(subcategoryDto.getName()) == null)
                subcategoryDao.save(new Subcategory(subcategoryDto));
        });
    }

    @Transactional
    public void ensureCities() {
        cityDtos.forEach(cityDto -> {
            if (cityDao.findByName(cityDto.getName()) == null)
                cityDao.save(new City(cityDto));
        });
    }

    @Transactional
    public void ensureCountries() {
        countryDtos.forEach(countryDto -> {
            if (countryDao.findByName(countryDto.getName()) == null)
                countryDao.save(new Country(countryDto));
        });
    }

    @Transactional
    public void ensureLocationCategory() {
        locationCategoryDtos.forEach(locationCategoryDto -> {
            if (locationCategoryDao.findByLocationType(locationCategoryDto.getLocationType()) == null)
                locationCategoryDao.save(new LocationCategory(locationCategoryDto));
        });
    }

    @Transactional
    public void ensureLocation() {
        ensureLocationCategory();
        ensureCities();
        ensureCountries();
        locationDtos.forEach(locationDto -> {
            if (locationDao.find(locationDto) == null)
                locationDao.save(locationDto);
        });
    }

    @Transactional
    public void ensureAddress() {
        ensureLocation();
        addressDtos.forEach(addressDto -> {
            if (addressDao.find(addressDto) == null)
                addressDao.save(addressDto);
        });
    }

    @Test
    @Transactional
    public void createTest() {
        String createUrl = "http://localhost:" + randomServerPort + "/api/event";
        AddressDto addressDto = addressDtos.get(0);
        CategoryDto categoryDto = categoryDtos.get(0);
        SubcategoryDto subcategoryDto = subcategoryDtos.get(0);
        ArrayList<PerformerDto> performerDtos = new ArrayList<>(EventServiceTests.performerDtos.subList(0, 3));
        EventDto eventDto = new EventDto("testEvent", addressDto, categoryDto, subcategoryDto, performerDtos, new Date(), new Date());
        RestTemplate createTemplate = new RestTemplate();
        CreateEventResponse response = createTemplate.postForObject(createUrl, eventDto, CreateEventResponse.class);
        //assertions
    }
}

Aucun commentaire:

Enregistrer un commentaire