javaspringspring-bootgradlespring-cloud-contract

Spring cloud contract: tests based on contracts are not generated on producer side at all


Tests are not being generated based on contracts in java. I used gradle to configure spring-cloud-contract and used java for contracts. When I run ./gradlew clean build -x test, it throws illegal state exception because of absence of contract tests which I configured in build.gradle (throw new IllegalStateException("No tests were found. Failing the build")).

build.gradle:

contracts {
      contractsDslDir = file("src/test/resources/contracts")
      testFramework = "JUNIT"
      packageWithBaseClasses = 'com.epam.training.microservicefoundation.resourceservice'
      baseClassMappings {
      baseClassMapping(".rest.*", "com.epam.training.microservicefoundation.resourceservice.RestBase")
   }
   contractsDslDir = new File(project.rootDir, "src/test/java/contracts")
}

contractTest {
    useJUnitPlatform()
    testLogging {
       exceptionFormat = 'full'
    }
    afterSuite { desc, result ->
       if (!desc.parent) {
           println "Results: (${result.testCount} tests, ${result.successfulTestCount} successes, ${result.failedTestCount} failures, ${result.skippedTestCount} skipped)"
           boolean skipTests = Boolean.parseBoolean(project.findProperty('SKIP_TESTS') ?: "false")
         if (result.testCount == 0 && !skipTests) {
            throw new IllegalStateException("No tests were found. Failing the build")
         }
       }
    }
}

publishing {
    publications {
        mavenJava(MavenPublication) {
           artifact bootJar

           artifact verifierStubsJar

        // https://github.com/spring-gradle-plugins/dependency-management-plugin/issues/273
           versionMapping {
               usage("java-api") {
                   fromResolutionOf("runtimeClasspath")
               }
               usage("java-runtime") {
                   fromResolutionResult()
               }
           }
       }
    }
}

contract in java:

public class shouldGet implements Supplier<Contract> {

   @Override
   public Contract get() {
       return Contract.make(contract -> {
           contract.request(request -> {
               request.method("GET");
               request.url("/api/v1/resources/123");
               request.headers(headers -> headers.accept(ResourceType.MP3.getMimeType()));
           });
           contract.response(response -> {
               response.status(response.OK());
               response.body(response.fileAsBytes("resources/files/mpthreetest.mp3"));
               response.headers(headers -> headers.contentType(ResourceType.MP3.getMimeType()));
           });
      });
   }
}

base class for generated class by producer:

public abstract class RestBase {
ResourceController resourceController;

   @BeforeEach
   public void setup() {
       resourceController = new ResourceController(new FakeResourceService());
       EncoderConfig encoderConfig = new EncoderConfig().appendDefaultContentCharsetToContentTypeIfUndefined(false);
       RestAssuredMockMvc.config = new RestAssuredMockMvcConfig().encoderConfig(encoderConfig);
       RestAssuredMockMvc.standaloneSetup(resourceController);

   }

   static class FakeResourceService implements ResourceService {

       @Override
       public ResourceRecord save(MultipartFile file) {
           return null;
       }

       @Override
       public InputStreamResource getById(long id) {
           try {
               File file = ResourceUtils.getFile("classpath:files/mpthreetest.mp3");
               return new InputStreamResource(new FileInputStream(file));
           } catch (FileNotFoundException ex) {
               return null;
           }
       }

       @Override
       public List<ResourceRecord> deleteByIds(long[] ids) {
           return null;
       }
   }
}

file structure: enter image description here

output of generated tests in build file:

@SuppressWarnings("rawtypes")
public class RestTest extends RestBase {

}

there is no any test generated, but there should be corresponding test based on contract shouldGet.java


Solution

  • I realized that the issue was related to the response body in the contract: response.body(response.fileAsBytes("resources/files/mpthreetest.mp3")); Apparently it could not read from the resources folder, after I move the file to the same package where the contract file located, then the issue was resolved successfully:

    enter image description here

    And, changed the response body to response.body(response.fileAsBytes("mpthreetest.mp3"));

    P.S: Using Supplier<Collection<Contract>> interface also might prevent the contract to get generated, I changed it to just Supplier<Contract>