Spring cloud contract: Generated test doesn't have MockMVC configured and fails compile
Asked Answered
S

2

8

I am running into this "You haven't configured a MockMVC instance." exception when "mvn clean install".

Running

org.springframework.cloud.contract.verifier.tests.ContractVerifierTest Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.185 sec <<< FAILURE! - in org.springframework.cloud.contract.verifier.tests.ContractVerifierTest validate_shouldGetAmenities(org.springframework.cloud.contract.verifier.tests.ContractVerifierTest) Time elapsed: 0.184 sec <<< ERROR! java.lang.IllegalStateException: You haven't configured a MockMVC instance. You can do this statically

or using the DSL:

given(). mockMvc(..). ..

The thing is, the test that throws this exception is a test that is generated based on a contract.

Here is the contract.

package contracts

org.springframework.cloud.contract.spec.Contract.make {
    request {
        method 'GET'
        url '/abc/def/serviceA?catalog=x'
        body("")
    }
    response {
        status 200
        body(""
        )
        headers {
            contentType(applicationJsonUtf8())
        }
    }
}

Here is the generated test.

package org.springframework.cloud.contract.verifier.tests;

public class ContractVerifierTest {

@Test
public void validate_shouldGetMyStuff() throws Exception {
        // given:
        MockMvcRequestSpecification request = given()
                .body("\"\"");

        // when:
            ResponseOptions response = given().spec(request)
                .get("/abc/def/serviceA?catalog=x");

        // then:
            assertThat(response.statusCode()).isEqualTo(200);
            assertThat(response.header("Content-Type")).matches("application/json;charset=UTF-8.*");
        // and:
            String responseBody = response.getBody().asString();
            assertThat(responseBody).isEqualTo("");
    }

}

Obviously, MockMVC instance is not started in the generated test. The suggestion in the exception message is to start it in the test. However, it is a generated test(under "target" folder). It doesn't matter what I add there, it gets wiped out after "mvn clean install".

Has anyone run into this? Is my contract wrong? That's why it didn't get the MockMVC start part generated in the generated test?

The other concern is the URL in the contract is a simple get. It does return a message in Json format. But for now, I just want to make it very simple by only verifying status code 200 without checking the message.

One more thing about this URL is that I tried this url in postman and get the reponse. I assume this should be the url I use in my contract. Is this assumption wrong? Do I need to form this url in contract differently?

Also, in postman when I request this 'GET' with this url, I don't have anything in "body". That's why I left "body" in contract as empty (""). Is this the right way doing it? Could this affect the generated test?

Any hints will be appreciated.

at   com.jayway.restassured.module.mockmvc.internal.MockMvcRequestSenderImpl.performRequest(MockMvcRequestSenderImpl.java:101)
at com.jayway.restassured.module.mockmvc.internal.MockMvcRequestSenderImpl.sendRequest(MockMvcRequestSenderImpl.java:296)
at com.jayway.restassured.module.mockmvc.internal.MockMvcRequestSenderImpl.get(MockMvcRequestSenderImpl.java:367)
at com.jayway.restassured.module.mockmvc.internal.MockMvcRequestSenderImpl.get(MockMvcRequestSenderImpl.java:47)
at com.jayway.restassured.module.mockmvc.internal.MockMvcRequestSpecificationImpl.get(MockMvcRequestSpecificationImpl.java:565)
at com.jayway.restassured.module.mockmvc.internal.MockMvcRequestSpecificationImpl.get(MockMvcRequestSpecificationImpl.java:42)
at
  org.springframework.cloud.contract.verifier.tests.ContractVerifierTest.validate_shouldGetAmenities(ContractVerifierTest.java:23)
Sproul answered 23/2, 2017 at 2:28 Comment(1)
The stacktrace after "given(). mockMvc(..). .." is inserted at the end of the post. Somehow I can't get it inserted in the middle.Sproul
S
7

It turns out that I need to add the base class that I am missing(like the FraudBase.java) in the sample. That's where the MockMvc is being instantiated.

Sproul answered 28/2, 2017 at 0:15 Comment(7)
I'm pretty sure that it's written in the documentation a couple of times that you need a base class.Sassanid
it's mandatory - without this we will not be able to set up the mock mvc contextSassanid
That should be in the error message as one possible cause :PSymphonious
Thanks Eric for posting this answer. I run into same problem, but can't figure out full solution. Please, can you post full solution with Base class and full implementation of base class. Please.Sarette
Hi Renat, please refer to this document and search this term on the page, "public class FraudBase". It is this base class you need to make work in your codebase. The base class I made work is our company IP and I cannot post it. And it's not very relevant to what you need to do in your codebase. But one important thing is that you need to have this in the base class. @Before public void setup() { RestAssuredMockMvc.standaloneSetup(new FraudDetectionController(), new FraudStatsController(stubbedStatsProvider())); }Sproul
That RestAssuredMockMvc.standaloneSetup() is what Spring Cloud Contract uses to fire up a local MockMvc to run the stubs.jar with. I remember I missed this line and that was why it didn't work for me and triggered this post. Besides this line, the rest is whatever you need in your context to make the local Application to start up. It could be a Class name like "whatever.class" in the annotation or some webApplicationContext you need to provide.Sproul
Sorry, forgot to paste the link of the doc that I mentioned above, here it is, cloud.spring.io/spring-cloud-contract/… please search for "public class FraudBase".Sproul
P
0
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.contract.verifier.messaging.boot.AutoConfigureMessageVerifier;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;

import static io.restassured.module.mockmvc.RestAssuredMockMvc.mockMvc;

@ExtendWith(SpringExtension.class)
@SpringBootTest
@AutoConfigureMockMvc
@AutoConfigureMessageVerifier
public abstract class SpringCloudContractProducerApplicationTests {

    @Autowired
    private MockMvc mockMvc;

    @BeforeEach
    public void setup() {
        mockMvc(mockMvc);
    }

    @Test
    void contextLoads() {
    }

}

// That works for me

Papistry answered 2/10, 2024 at 5:52 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.