title: Run/Debug JUnit 5 Tests using Gradle and Mapstruct
body: <p>I am trying to run and debug JUnit 5 Tests that use Mapstruct using both Visual Studio Code and Eclipse, but with no luck.</p>
  
  <p>What works is to run the Test goal on Gradle. It runs the tests properly and show a result but when I try to run or debug the same test "manually" using the IDE, it throws an exception, always related to not being able to find the Mapper implementations or not being able to Autowire the clases, etc. </p>
  
  <p>I have tried different things but with similar results, such as Autowire the Mapper, creating an instance of the Mapper in a method using @Before annotation... but always with no success.</p>
  
  <p>Here is an example of a Mapper:</p>
  
  <p><strong>AddressMapper.java</strong></p>
  
  <pre><code>package com.myorg.ccr.simulator.b2b.mapping;
  
  import com.myorg.myproject.model.AddressDTO;
  import com.myorg.myproject.model.StateDTO;
  import com.myorg.xsd.b2b.upsertcustomer.Address;
  
  import org.mapstruct.AfterMapping;
  import org.mapstruct.BeanMapping;
  import org.mapstruct.InheritInverseConfiguration;
  import org.mapstruct.Mapper;
  import org.mapstruct.Mapping;
  import org.mapstruct.MappingTarget;
  import org.mapstruct.ReportingPolicy;
  import org.mapstruct.factory.Mappers;
  
  @Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE,
      unmappedSourcePolicy = ReportingPolicy.IGNORE,
      uses = {DateMapper.class, UUIDMapper.class, StateMapper.class})
  public interface AddressMapper {
      AddressMapper INSTANCE = Mappers.getMapper(AddressMapper.class);
  
      @BeanMapping(ignoreByDefault = true)
      @Mapping(target = "externalAddressId", source = "externalAddressId")
      @Mapping(target = "street1", source = "streetAddress")
      @Mapping(target = "street2", source = "streetAddress2")
      @Mapping(target = "postOfficeBox", source = "POBox")
      @Mapping(target = "city", source = "city")
      @Mapping(target = "postalCode", source = "postalCode")
      @Mapping(target = "salutation", source = "recipientSalutation")
      @Mapping(target = "phone", source = "recipientPhone")
      @Mapping(target = "comments", source = "comments")
      AddressDTO addressToAddressDTO(Address address);
  
      @InheritInverseConfiguration
      Address addressDTOToAddress(AddressDTO address);
  
      @AfterMapping
      default void setStatus(Address address, @MappingTarget AddressDTO addressDTO) {
          StateDTO state = StateMapper.INSTANCE.addressToState(address);
          addressDTO.setStatus(state);
      }
  
      @AfterMapping
      default void setSourceCreatedUpdatedDate(Address address, @MappingTarget AddressDTO addressDTO) {
          if (address != null) {
              addressDTO.setSourceCreatedDate(DateMapper.asDate(address.getSourceCreatedDate()));
              addressDTO.setSourceUpdatedDate(DateMapper.asDate(address.getSourceUpdatedDate()));
          }
      }
  
      @AfterMapping
      default void useTypeToAddressNumber(Address address, @MappingTarget AddressDTO addressDTO) {
          if (address != null &amp;&amp; address.getType() != null &amp;&amp; !address.getType().isEmpty()) {
  
              switch (address.getType()) {
                  case "Billing":
                      addressDTO.setAddressNumber(1);
                      break;
                  case "Delivery":
                      addressDTO.setAddressNumber(2);
                      break;
                  case "Packing Station":
                      addressDTO.setAddressNumber(3);
                      break;
                  case "Post Office":
                      addressDTO.setAddressNumber(4);
                      break;
                  default:
                      addressDTO.setAddressNumber(null);
              }   
          }
      }
  
      @AfterMapping
      default void addressNumberToType(AddressDTO addressDTO, @MappingTarget Address address) {
          if (addressDTO != null &amp;&amp; addressDTO.getAddressNumber() != null) {
  
              switch (addressDTO.getAddressNumber()) {
                  case 1:
                      address.setPrimaryFlag("Y");
                      address.setType("Billing");
                      break;
                  case 2:
                      address.setPrimaryFlag("N");
                      address.setType("Delivery");
                      break;
                  case 3:
                      address.setPrimaryFlag("N");
                      address.setType("Packing Station");
                      break;
                  case 4:
                      address.setPrimaryFlag("N");
                      address.setType("Post Office");
                      break;
                  default:
                      address.setPrimaryFlag("N");
                      address.setType(null);
              }   
          }
      }
  
      @AfterMapping
      default void contactFullname(Address address, @MappingTarget AddressDTO addressDTO) {
          String firstName = address.getRecipientFirstName();
          String lastName = address.getRecipientLastName();
          if (firstName != null &amp;&amp; !firstName.isEmpty() &amp;&amp; lastName != null &amp;&amp; !lastName.isEmpty()) {
              addressDTO.setContactFullname(firstName + " " + lastName);
          } else if ((firstName == null || firstName.isEmpty()) &amp;&amp; lastName != null &amp;&amp; !lastName.isEmpty()) {
              addressDTO.setContactFullname(lastName);
          } else if (firstName != null &amp;&amp; !firstName.isEmpty()  &amp;&amp; (lastName == null || lastName.isEmpty())) {
              addressDTO.setContactFullname(firstName);
          } 
      }
  
      @AfterMapping
      default void addressRecipientName(AddressDTO addressDTO, @MappingTarget Address address) {
          if (addressDTO != null &amp;&amp; addressDTO.getContactFullname() != null &amp;&amp; !addressDTO.getContactFullname().isEmpty()) {
              address.setRecipientFirstName(addressDTO.getContactFullname());
          }
      }
  
      @AfterMapping
      default void setActiveFlag(AddressDTO addressDTO, @MappingTarget Address address) {
          String activeFlag = "N";
          if (addressDTO != null) { 
              activeFlag = StateMapper.INSTANCE.stateToActiveFlag(addressDTO.getStatus());
          } 
          address.setActiveFlag(activeFlag);
      }
  
      @AfterMapping
      default void setDeletedFlag(AddressDTO addressDTO, @MappingTarget Address address) {
          String deletedFlag = "N";
          if (addressDTO != null) { 
              deletedFlag = StateMapper.INSTANCE.stateToDeletedFlag(addressDTO.getStatus());
          } 
          address.setDeletedFlag(deletedFlag);
      }
  
      @AfterMapping
      default void setCountry(AddressDTO addressDTO, @MappingTarget Address address) {
          String country = null;
          if (addressDTO != null &amp;&amp; addressDTO.getCountry() != null &amp;&amp; !addressDTO.getCountry().isEmpty()) { 
              country = addressDTO.getCountry();
          } 
          address.setISOCountryCode(country);
      }
  }
  </code></pre>
  
  <p>Here is an example of a Test:</p>
  
  <p><strong>AddressMapperTest.java</strong></p>
  
  <pre><code>package com.myorg.ccr.simulator.b2b.messaging.mapping;
  
  import com.myorg.myproject.model.AddressDTO;
  import com.myorg.myproject.model.StateDTO;
  import com.myorg.ccr.simulator.b2b.mapping.AddressMapper;
  import com.myorg.ccr.simulator.b2b.messaging.mapping.helpers.AddressMappingHelper;
  import com.myorg.xsd.b2b.upsertcustomer.Address;
  import org.junit.jupiter.api.Test;
  import org.junit.jupiter.api.TestInstance;
  import org.junit.jupiter.api.extension.ExtendWith;
  import org.springframework.test.context.junit.jupiter.SpringExtension;
  import org.threeten.bp.OffsetDateTime;
  import org.threeten.bp.format.DateTimeFormatter;
  
  import static org.assertj.core.api.Assertions.assertThat;
  
  @ExtendWith(SpringExtension.class)
  @TestInstance(TestInstance.Lifecycle.PER_CLASS)
  public class AddressMapperTest {
      private AddressMapper mapper = AddressMapper.INSTANCE;
  
      @Test
      public void xsdAddressToAddressTest() {
          Address xsdAddress = new Address();
  
          xsdAddress.setActiveFlag("Y");
          xsdAddress.setDeletedFlag("N");
          xsdAddress.setType("Billing");
          xsdAddress.setPrimaryFlag("N");
          xsdAddress.setExternalAddressId("15106794");
          xsdAddress.setStreetAddress("Some Street Name 70 E/24");
          xsdAddress.setStreetAddress2("Some Building info 123");
          xsdAddress.setPOBox("08905");
          xsdAddress.setCity("BiaÅ‚ystok");
          xsdAddress.setPostalCode("15-181");
          xsdAddress.setISOCountryCode("PL");
          xsdAddress.setRecipientLastName("Mustermann");
          xsdAddress.setRecipientFirstName("Max");
          xsdAddress.setRecipientSalutation("Mr.");
          xsdAddress.setRecipientPhone("512341234");
          xsdAddress.setAddressInvalidFlag("Y");
          xsdAddress.setComments("A comment from the user.");
          xsdAddress.setSourceCreatedDate("2016-06-14T21:19:33+02:00");
          xsdAddress.setSourceUpdatedDate("2019-09-05T11:26:20+02:00");
  
          AddressDTO address = mapper.addressToAddressDTO(xsdAddress);
          assertThat(address.getId()).isNull();
          assertThat(address.getStatus()).isNotNull();
          assertThat(address.getStatus().getValue()).isNotNull();
          assertThat(address.getStatus().getValue()).isEqualTo(1);
          assertThat(address.getExternalAddressId()).isEqualTo("15106794");
          assertThat(address.getAddressNumber()).isEqualTo(1);
          assertThat(address.getStreet1()).isEqualTo("Some Street Name 70 E/24");
          assertThat(address.getStreet2()).isEqualTo("Some Building info 123");
          assertThat(address.getCity()).isEqualTo("BiaÅ‚ystok");
          assertThat(address.getPostalCode()).isEqualTo("15-181");
          assertThat(address.getPostOfficeBox()).isEqualTo("08905");
          assertThat(address.getCountry()).isNull(); //This may change
          assertThat(address.getContactFullname()).isEqualTo("Max Mustermann");
          assertThat(address.getSalutation()).isEqualTo("Mr.");
          assertThat(address.getPhone()).isEqualTo("512341234");
          assertThat(address.getComments()).isEqualTo("A comment from the user.");
          assertThat(address.getSourceCreatedDate()).isEqualTo(OffsetDateTime.parse("2016-06-14T21:19:33+02:00",
              DateTimeFormatter.ISO_OFFSET_DATE_TIME));
          assertThat(address.getSourceUpdatedDate()).isEqualTo(OffsetDateTime.parse("2019-09-05T11:26:20+02:00",
              DateTimeFormatter.ISO_OFFSET_DATE_TIME));
      }
  
      @Test
      public void addressDTOToXSDAddressTest() {
          AddressDTO addressDTO = new AddressDTO();
          StateDTO state = new StateDTO();
          state.setValue(1);
          addressDTO.setStatus(state);
          addressDTO.setExternalAddressId("15106794");
          addressDTO.setAddressNumber(1);
          addressDTO.setStreet1("Some Street Name 70 E/24");
          addressDTO.setStreet2("Some Building info 123");
          addressDTO.setPostOfficeBox("08905");
          addressDTO.setCity("BiaÅ‚ystok");
          addressDTO.setPostalCode("15-181");
          addressDTO.setCountry("PL");
          addressDTO.setContactFullname("Max Mustermann");
          addressDTO.setSalutation("Mr.");
          addressDTO.setPhone("512341234");
          addressDTO.setComments("A comment from the user.");
          addressDTO.setSourceCreatedDate(OffsetDateTime.parse("2016-06-14T21:19:33+02:00",
              DateTimeFormatter.ISO_OFFSET_DATE_TIME));
          addressDTO.setSourceUpdatedDate(OffsetDateTime.parse("2019-09-05T11:26:20+02:00",
              DateTimeFormatter.ISO_OFFSET_DATE_TIME));
  
          Address address = mapper.addressDTOToAddress(addressDTO);
          assertThat(address.getActiveFlag()).isEqualTo("Y"); //This may change
          assertThat(address.getDeletedFlag()).isEqualTo("N"); //This may change
          assertThat(address.getExternalAddressId()).isEqualTo("15106794");
          assertThat(address.getPrimaryFlag()).isEqualTo("Y");
          assertThat(address.getStreetAddress()).isEqualTo("Some Street Name 70 E/24");
          assertThat(address.getStreetAddress2()).isEqualTo("Some Building info 123");
          assertThat(address.getCity()).isEqualTo("BiaÅ‚ystok");
          assertThat(address.getPostalCode()).isEqualTo("15-181");
          assertThat(address.getPOBox()).isEqualTo("08905");
          assertThat(address.getISOCountryCode()).isEqualTo("PL"); //This may change
          assertThat(address.getRecipientFirstName()).isEqualTo("Max Mustermann");
          assertThat(address.getRecipientSalutation()).isEqualTo("Mr.");
          assertThat(address.getRecipientPhone()).isEqualTo("512341234");
          assertThat(address.getComments()).isEqualTo("A comment from the user.");
          assertThat(address.getSourceCreatedDate()).isEqualTo("2016-06-14T21:19:33+02:00");
          assertThat(address.getSourceUpdatedDate()).isEqualTo("2019-09-05T11:26:20+02:00");
      }
  
      @Test
      public void dynamicXSDAddressToAddressDTOTest() {
          AddressMappingHelper mappingHelper = new AddressMappingHelper();
  
          while (mappingHelper.hasNext()) {
              mappingHelper.nextXSDAddress();
              Address xsdAddress =  mappingHelper.getExpectedAddress();
              AddressDTO address = mapper.addressToAddressDTO(xsdAddress);
              AddressDTO expectedAddress = mappingHelper.getExpectedAddressDTO();
              assertThat(address).usingRecursiveComparison().isEqualTo(expectedAddress);
          }
      }
  
      @Test
      public void dynamicAddressDTOToXSDAddressTest() {
          AddressMappingHelper mappingHelper = new AddressMappingHelper();
  
          while (mappingHelper.hasNext()) {
              mappingHelper.nextXSDAddress();
              AddressDTO addressDTO =  mappingHelper.getExpectedAddressDTO();
              Address address = mapper.addressDTOToAddress(addressDTO);
              Address expectedAddress = mappingHelper.getExpectedAddressFromDTO();
              System.out.println(address);
              System.out.println(expectedAddress);
              assertThat(address).usingRecursiveComparison().isEqualTo(expectedAddress);
          }
      }
  }
  </code></pre>
  
  <p>Here is the build.gradle file:</p>
  
  <p><strong>build.gradle</strong></p>
  
  <pre><code>buildscript {
    ext {
      springBootVersion = '2.1.5.RELEASE'
      jmsVersion        = '2.0.1'
      jaxbApiVersion = '2.2.7'
      flywayVersion = '5.2.1'
  
      // tests
      junitJuniper = '5.1.1'
      junitGradlePlatformVersion = '1.1.0'
      assertJCoreVersion = '3.14.0'
  
      mapstructVersion = "1.3.0.Final"
  
      swaggerCodgenVersion = '3.0.13'
      jacksonThreetenVersion = '2.6.4'
  
    }
    repositories {
      mavenCentral()
      jcenter()
    }
    dependencies {
      classpath "org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion"
    }
  }
  
  apply plugin: 'idea'
  apply plugin: 'java'
  apply plugin: 'org.springframework.boot'
  apply plugin: 'io.spring.dependency-management'
  apply plugin: "checkstyle"
  
  group = 'com.myorg.ccr'
  sourceCompatibility = '1.8'
  targetCompatibility = '1.8'
  
  repositories {
    mavenCentral()
    maven {
      credentials {
        username = "$mavenUser"
        password = "$mavenPassword"
      }
      url "https://myorg.jfrog.io/myorg/libs-snapshot"
    }
    maven {
      credentials {
        username = "$mavenUser"
        password = "$mavenPassword"
      }
      url "https://myorg.jfrog.io/myorg/libs-release"
    }
  }
  
  sourceSets {
    main {
      java {
        srcDir 'src/schema'
      }
    }
  }
  
  configurations {
    jaxb_generateSources
  }
  
  dependencies {
    annotationProcessor 'org.projectlombok:lombok:1.18.6'
    annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
  
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-security', version: springBootVersion
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: springBootVersion
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: springBootVersion
  
    // https://mvnrepository.com/artifact/javax.jms/javax.jms-api
    implementation group: 'javax.jms', name: 'javax.jms-api', version: jmsVersion
    implementation group: 'org.springframework', name: 'spring-jms', version: '5.1.9.RELEASE'
  
    implementation group: 'com.tibco', name: 'tibjms', version: '8.2.1'
    implementation group: 'com.myorg.ccr.client', name: 'customer-client', version: '1.1.0-SNAPSHOT'
    compile group: 'com.myorg.login', name: 'login-lib-java-spring', version: '1.5.0-SNAPSHOT'
  
    runtimeOnly group: 'org.postgresql', name: 'postgresql'
    runtimeOnly group: 'com.h2database', name: 'h2'
    implementation group: 'org.flywaydb', name: 'flyway-core', version: flywayVersion
  
    testImplementation "org.junit.jupiter:junit-jupiter-api:$junitJuniper"
    testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitJuniper"
    testCompile "org.assertj:assertj-core:$assertJCoreVersion"
    testCompile("org.springframework.boot:spring-boot-starter-test")
    testCompile("org.springframework.security:spring-security-test")
  
    jaxb_generateSources(
      [group: 'com.sun.xml.bind', name: 'jaxb-xjc', version: jaxbApiVersion],
      [group: 'com.sun.xml.bind', name: 'jaxb-impl', version: jaxbApiVersion],
    )
  
    compileOnly 'org.projectlombok:lombok:1.18.6'
    compileOnly "org.springframework.boot:spring-boot-configuration-processor"
  
    implementation "org.mapstruct:mapstruct:${mapstructVersion}"
    annotationProcessor "org.mapstruct:mapstruct-processor:${mapstructVersion}"
  
    // If you are using mapstruct in test code
    testAnnotationProcessor "org.mapstruct:mapstruct-processor:${mapstructVersion}"
  
    compile "io.swagger.codegen.v3:swagger-codegen-maven-plugin:$swaggerCodgenVersion"
    compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jacksonThreetenVersion"
  }
  
  clean {
    delete 'src/schema'
  }
  
  task jaxb_generateSources {
  
  
    System.setProperty('javax.xml.accessExternalSchema', 'all')
    def jaxbTargetDir = file("src/schema")
  
    doLast {
      ext.generateSources = { packageName, xsdSchemaLocation -&gt;
        ant.taskdef(
                name: 'xjc',
                classname: 'com.sun.tools.xjc.XJCTask',
                classpath: configurations.jaxb_generateSources.asPath
        )
        ant.jaxbTargetDir = jaxbTargetDir
  
        ant.xjc(
                destdir: '${jaxbTargetDir}',
                package: packageName,
                schema: xsdSchemaLocation,
                encoding: 'UTF-8'
        )
      }
  
      jaxbTargetDir.mkdirs()
  
      // b2c
      generateSources('com.myorg.xsd.upsertcustomer', 'src/main/resources/b2c.xsd/doAsyncUpsertCustomer_BDM_DST.xsd')
      // b2b
      generateSources('com.myorg.xsd.b2b.upsertcustomer', 'src/main/resources/b2b/xsd/doAsyncUpsertAccount_BDM_DST.xsd')
  
    }
  }
  
  compileJava {
    dependsOn jaxb_generateSources
  }
  
  test {
    useJUnitPlatform()
    // TODO: Is actual an integration and no unit test
    exclude '**/ContactControllerTest.class'
  }
  
  task integrationTest(type: Test) {
    useJUnitPlatform()
    description = 'Runs the integration tests.'
    group = 'verification'
    include '**/ContactControllerTest.class'
  }
  
  tasks.withType(Checkstyle) {
    exclude '**/b2bkam/**'
  }
  
  checkstyle {
    config = rootProject.resources.text.fromFile("${rootDir}/config/checkstyle/checkstyle_ccr-simulator_v1.xml")
    toolVersion '8.11'
  }
  </code></pre>
  
  <p>Thank you in advance,</p>
  
  <p>Aitor</p>