2

I have made a Rest API with Spring frame work, the API will take a date and find a record from database and return the record, in the database it will have a start date and end date columns, based on the given date, it should return all records that given date is in between.

I am using oracle database java 8 and spring frome work boot 2.1.2 release, the problem is when I make a junit test with Mokito to test the REST api i made, when I pass in a date, when my method receives the date it changed the date, I have found that seems when it receives the date it converted to different timezone (+1 timezone), and my local computer timeZone is set to -6 timeZone, if I covert the date to +1, the test will be success, if I just pass in the date object, it will auto convert it to +1 timezone which will be miss match.

I would like to know why is that since I testing them in the same place, how come date still get changed, and with understanding I prefer a solution of it.

so I will have a table in data base with product_category_id(long), start_date(date), end_date(date) and second table with Product_id(long), type_code(short), price(double), product_category_id and they are associated with product_category_id

here is the method in controller file

@GetMapping("/{startDate}")
  public ResponseEntity<List<ProductCategoryResource>> findByDate(
      @PathVariable("startDate") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) final Date startDate)
  {
    final List<ProductCategory> productCategoryList =
        ProductCategoryService.findByDate(startDate);

    final List<ProductCategoryResource> productCategoryResourceList = new ArrayList<>();

    for (final ProductCategory productCategory: productCategoryList)
    {
      productCategoryResourceList.add(new ProductCategoryResource(productCategory));
    }

    return new ResponseEntity<>(ProductCategoryResourceList, HttpStatus.OK);
  }

here is service

public List<ProductCategory> findByDate(final Date searchDate)
  {

    return ProductCategoryRepository
        .findByStartDateLessThanEqualAndEndDateGreaterThanEqual(searchDate,
            searchDate);
  }

and repository is just an default interface extends CrudRepository, with findByStartDateLessThanEqualAndEndDateGreaterThanEqual method inside.

here is my junit test.

    public void findByDate() throws Exception{
    final String pattern = "yyyy-MM-dd";
    final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
    final Date searchDate = simpleDateFormat.parse("2018-05-22");

    //Here mock all return values and add to result list

    BDDMockito.given(ProductCategoryService.findByDate(searchDate)).willReturn(resultList);

    mvc.perform(MockMvcRequestBuilders.get("/productCategory/2018-05-22")
        .contentType(MediaType.APPLICATION_JSON)).andExpect(MockMvcResultMatchers.status().isOk())
        .andExpect(MockMvcResultMatchers.jsonPath("$[0].startDate", Matchers
            .startsWith(simpleDateFormat.format(resultList.get(0).getProductCategoryStartDate()))));
  }

so this will give an error $[0].startDate is null, which it did not return the mocked result list, I debug and found that when it hits the method in controller, the date changed to Mon May 21 18:00:00 CST 2018, so the date was not matching to the date I give in BDDMockito.given. but if I change my local timezone to +1, it will be exactly the same

I expected no matter which timezone I run the build of the project, the test never fails, it should always send same date due to it actually passed by url.

John
  • 33
  • 4
  • These might help - https://stackoverflow.com/questions/29027475/date-format-in-the-json-output-using-spring-boot/29028800 and https://stackoverflow.com/questions/46151633/how-to-make-default-time-zone-apply-in-spring-boot-jackson-date-serialization – Ajay Kumar May 16 '19 at 21:23
  • How are you initilizing the mock mvc? – Darren Forsythe May 16 '19 at 21:26
  • I use @Autowired private MockMvc mvc; – John May 16 '19 at 21:29
  • so now I am more worried if I deploy my application in one timezone and if another user in different timezone trying to use the service call my API and pass in the date through the url as what I showed in my junit test, when it reach my application will the date also get auto converted? – John May 16 '19 at 21:32
  • and thanks @Ajay Kumar , I have went through those two questions you send, and I dont think they are the same issue, my problem is more like how can I make sure my application does not change the date that user send in from different timeZone, becuase the date they send in from url should be exactly what they want to find from the database, its not going to change once its reach my application. if I have any misunderstood, please let me know. thanks – John May 16 '19 at 21:41
  • Are you able to use a `java.time.LocalDate` instead? This takes away all timezone concerns and gives you a plain old calendar date. – Not a JD May 16 '19 at 21:50
  • Thanks @Not a JD, it worked, so I have changed in my controller use LocalDate instead, and it solved everything, now when user pass in date, it not change any more, and my junit test is success, so it receives same date on both side now. thank you so much for the help. – John May 17 '19 at 14:16

0 Answers0