Search code examples
javaspring-bootunit-testingjunitoption-type

Spring Boot unit testing assertion error JSON object got a JSON array


I am unit testing in a spring boot application. But as the getProductById() method returns Optional of the object, I am not sure how to test it.

ProductController.java

@GetMapping("/products/{id}")
@Transactional(readOnly=true)
@Cacheable("product-cache")
public Product getProduct(@PathVariable("id") int id) {
        LOGGER.info("Finding product by id : "+id);
        return productRepository.findById(id).get();
}

MockTest.java

private static final String PRODUCTS_URL = "/productsapi/products";
private static final int PRODUCT_ID = 1;
private static final String CONTEXT_URL = "/productsapi";
private static final int PRODUCT_PRICE = 1000;
private static final String PRODUCT_DESCRIPTION = "Its awesome";
private static final String PRODUCT_NAME = "Macbook";

@Test
public void testGetProductById() throws JsonProcessingException, Exception {
        Product product = buildProduct();
        when(productRepository.findById(PRODUCT_ID)).thenReturn(Optional.of(product));
        
        ObjectWriter objectWriter = new ObjectMapper().writer().withDefaultPrettyPrinter();
        mockMvc.perform(get(PRODUCTS_URL).contextPath(CONTEXT_URL))
           .andExpect(status().isOk())
           .andExpect(content().json(objectWriter.writeValueAsString(Optional.of(product))));
}

private Product buildProduct() {
        Product product = new Product();
        product.setId(PRODUCT_ID);
        product.setName(PRODUCT_NAME);
        product.setDescription(PRODUCT_DESCRIPTION);
        product.setPrice(PRODUCT_PRICE);
        return product;
}

When I run the test, it fails with below error.

Error: java.lang.AssertionError: Expected: a JSON object got: a JSON array

It doesn't show any compilation error. But test case fails. I think it's the problem with conversion of product object into json.

So, little help in resolving this will be helpful!!


Solution

  • The controller method is only returning Product object which is a JSON {} and in the andExpect method you are asserting with array of JSON [{}], remove the Optional and only pass product object

    mockMvc.perform(get(PRODUCTS_URL).contextPath(CONTEXT_URL)).andExpect(status().isOk())
                .andExpect(content().json(objectWriter.writeValueAsString(product)));