Search code examples
springspring-bootjunitspring-test

Why my test does not pass and I get org.opentest4j.AssertionFailedError


I am taking the spring boot course for building a RESTFUL CashCard family API from spring Academy. But I get an unexpected result when I write the test.

this is my CashCard entity class

package com.stephane.cashcard.Entity;

public class CashCard {
    public CashCard(Long cardId, Double amount){}
}

My CashCardController class

package com.stephane.cashcard.Controller;

import com.stephane.cashcard.Entity.CashCard;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/cashcards")
public class CashCardController {
    @GetMapping("/{requestedId}")
    public ResponseEntity<CashCard> findById() {
        CashCard cashCard = new CashCard(99L, 0.0);
        return ResponseEntity.ok(cashCard);
    }
}

and finally my CashCardApplicationTests class

package com.stephane.cashcard;

import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.JsonPath;
import com.stephane.cashcard.Entity.CashCard;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

import static org.assertj.core.api.Assertions.assertThat;

/**
 * Cela démarrera notre application Spring Boot
 * et la rendra disponible pour que notre test
 * puisse y effectuer des requêtes.
 */
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class CashCardApplicationTests {

    /**
     * Injection Du module TestRestTemplate qui permettra
     * de faire des requêtes HTTP à l'application en cours d'execution
     *
     */
    @Autowired
    TestRestTemplate restTemplate;

    @Test
    void returnCashCardWhenDataIsSaved(){
        /**
         * Here we use restTemplate to make an HTTP GET request to our application endpoint /cashcards/99.
         *
         * restTemplate will return a ResponseEntity, which we've captured in a variable we've named response.
         * ResponseEntity is another helpful Spring object that provides valuable information
         * about what happened with our request. We will use this information throughout out tests in this course.
         */
        ResponseEntity<String> response = restTemplate.getForEntity("/cashcards/99", String.class);

        /**
         * We can inspect many aspects of the response, including the HTTP
         * Response Status code, which we expect to be 200 OK.
         */
        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);

        //Convertir la reponse qui est un String en un objet JSON
        DocumentContext documentContext = JsonPath.parse(response.getBody());



        /**
         * Nous attendons à ce que lorsque nous demandons
         * un cashCard avec l'identifiant 99, un Objet
         * JSON soit retourné avec quelque chose dans le champs id.
         *
         * Nous nous assurons par la suite que l'identifiant n'est pas nul
         */
        Number id = documentContext.read("$.id");
        assertThat(id).isEqualTo(99);
    }

}
 

and this what i get when i run test class

expected: 200 OK but was: 406 NOT_ACCEPTABLE org.opentest4j.AssertionFailedError: expected: 200 OK but was: 406 NOT_ACCEPTABLE ...


Solution

  • There are numerous issues here. I have fixed code and marked fixed with // XXX and explanation.

    Note that I never got the 406 failure, only a 500.

    public class CashCard {
        public CashCard(Long cardId, Double amount){
            this.cardId = cardId; // XXX missing
            this.amount = amount; // XXX missing
        }
        
        public Long cardId; // XXX missing so CashCard can't be serialised
        
        public Double amount; // XXX missing
        
    }
    

    CashCardController

    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("/cashcards")
    public class CashCardController {
    
        
        @GetMapping("/{requestedId}")
        public ResponseEntity<CashCard> findById(@PathVariable Long requestedId) { // XXX argument missing
            CashCard cashCard = new CashCard(requestedId, 0.0); // XXX populate cardId
            return ResponseEntity.ok(cashCard);
        }
    
    }
    

    CashCardApplicationTests class

    import com.jayway.jsonpath.DocumentContext;
    import com.jayway.jsonpath.JsonPath;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.boot.test.web.client.TestRestTemplate;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    
    import static org.assertj.core.api.Assertions.assertThat;
    
    /**
     * Cela démarrera notre application Spring Boot
     * et la rendra disponible pour que notre test
     * puisse y effectuer des requêtes.
     */
    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
    class CashCardApplicationTests {
    
        /**
         * Injection Du module TestRestTemplate qui permettra
         * de faire des requêtes HTTP à l'application en cours d'execution
         *
         */
        @Autowired
        TestRestTemplate restTemplate;
    
        @Test
        void returnCashCardWhenDataIsSaved(){
            /**
             * Here we use restTemplate to make an HTTP GET request to our application endpoint /cashcards/99.
             *
             * restTemplate will return a ResponseEntity, which we've captured in a variable we've named response.
             * ResponseEntity is another helpful Spring object that provides valuable information
             * about what happened with our request. We will use this information throughout out tests in this course.
             */
            ResponseEntity<String> response = restTemplate.getForEntity("/cashcards/99", String.class);
    
            /**
             * We can inspect many aspects of the response, including the HTTP
             * Response Status code, which we expect to be 200 OK.
             */
            assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
    
            //Convertir la reponse qui est un String en un objet JSON
            DocumentContext documentContext = JsonPath.parse(response.getBody());
    
    
    
            /**
             * Nous attendons à ce que lorsque nous demandons
             * un cashCard avec l'identifiant 99, un Objet
             * JSON soit retourné avec quelque chose dans le champs id.
             *
             * Nous nous assurons par la suite que l'identifiant n'est pas nul
             */
            Number id = documentContext.read("$.cardId"); // XXX $.id
            assertThat(id).isEqualTo(99);
        }
    
    }
     
    

    The test then passes.

    Junit results

    I am using Java 11, spring-boot-starter-parent 2.7.5.