Search code examples
spring-bootpact

Spring Boot test: get @Autowired to work without using `SpringRunner`


I am writing a pact provider test in a Spring Boot application. The controller has two dependencies for which one of them should be mocked and the other one shouldn't.

Since I am writing the pact test (which I'm new to it), I have to use @RunWith(RestPactRunner.class) on top of my test class.

in my test class I use @Autowired on the dependency that I don't want to mock but since I can't use SpringRunner my test doesn't know how to find the dependency and leaves it as null.

Here is the pact provider test:

@RunWith(RestPactRunner.class)
@Provider("provider_name")
@PactFolder("target/pacts")
public class SampleProviderTest {
    private MetadataController metadataController;

    @Mock
    private BlockService blockService; // dependency #1: to be mocked

    @Autowired
    private BlockMapper blockMapper; // dependency #2: to be injected

    @TestTarget
    public final MockMvcTarget target = new MockMvcTarget();

    @Before
    public void before() {
        initMocks(this);
        metadataController = new MetadataController(blockService, blockMapper);
        target.setControllers(metadataController);
    }


    /*
    * you can ignore the rest of this test class
    */


    @State("block info")
    public void blockInfo() {
        Block requestedBlock = new Block();
        when(blockService.getBlockInfo(123L, 12345L, "S1", "B1")).thenReturn(requestedBlock);
    }

}

Question:
- how do I get this test to pick up the right implementation for the dependency #2 above (blockMapper)? right now it remains null


Solution

  • after struggling with how to find the BlockMapper (actual implementation) without using @Autowired I finally used mapstruct's Mapper class to find the implementation in my test, that's how I did it:

    @RunWith(RestPactRunner.class)
    @Provider("provider_name")
    @PactFolder("target/pacts")
    public class SampleProviderTest {
        private MetadataController metadataController;
    
        @Mock
        private BlockService blockService; // dependency #1: to be mocked
    
        @TestTarget
        public final MockMvcTarget target = new MockMvcTarget();
    
        @Before
        public void before() {
            initMocks(this);
    
            // dependency #2: to be injected
            BlockMapper blockMapper = Mappers.getMapper(BlockMapper.class);
    
            metadataController = new MetadataController(blockService, blockMapper);
            target.setControllers(metadataController);
        }
    
    
        /*
        * removed the remainder...
        */
    }