Tsvetoslav Tsvetkov
Tsvetoslav Tsvetkov

Reputation: 1176

MockBean doesn't work in Spring boot integration test

I have Spring Integration test where I'm trying to Mock some of my Beans. For some reason although I Mocked them they are NULL. Here is code snippet:

The Bean which I want to Mock

@Component
public class MockWS {

    public String callSoapClient() throws JAXBException{
        return "CallSoapCl";
    }
}

The class where the Bean is used

public class SmDpES2PortImpl implements ES2SmDp {
    @Autowired
    private MockWS mock;

    @Override
    public void es2DownloadProfile(ES2DownloadProfileRequest parameters) {
         try {
            LOG.info("\n\n\n TEST BEAN: " + mock.callSoapClient() + "\n\n");
          }
     }  
}

Spring boot integration test where the Bean has been mocked

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class ES2SmDpApplicationTests {

    @MockBean(name="mockWS")
    MockWS mockService;

    @Test
    public void test1Es2DownloadProfile_Sucess() throws MalformedURLException, JAXBException, SOAPException {
        when(mockService.callSoapClient()).thenReturn("CallMockCLient");
    }
}

Output from the build execution: TEST BEAN: null

Upvotes: 4

Views: 12384

Answers (2)

hello_earth
hello_earth

Reputation: 1562

In my case the following combination of annotations worked:

@RunWith(SpringRunner.class) 
@SpringBootTest(classes = { ControllerThatIAmTesting.class }) 
@AutoConfigureMockMvc(addFilters = false) // if using MockMvc object

But I had to declare explicitly both Autowired objects that I use in the ControllerThatIAmTesting in the test class with @MockBean annotation - otherwise Spring would complain that it cannot find suitable implementation - incidentally both my interfaces and their implementations are in the same corresponding packages

Also, using @WebMvcTest instead of @SpringBootTest (other suggest it as more specific scenario) resulted in Spring failing to find and initialize some other @Autowired dependencies from my @Configuration classes.

Related posts post1 post2 post3

Upvotes: 2

Lorelorelore
Lorelorelore

Reputation: 3393

You should mock an interface, not a class. Also, SmDpES2PortImpl must be a Spring bean. Try the following:

Interface:

public interface IMockWS {

    public String callSoapClient() throws JAXBException;
}

Component class:

@Component
public class MockWS implements IMockWS {

    @Override
    public String callSoapClient() throws JAXBException{
        return "CallSoapCl";
    }
}

Service class:

@Service //Also @Component is a good alternative
public class SmDpES2PortImpl implements ES2SmDp {
    @Autowired
    private IMockWS mock; //Notice that you are wiring an interface

    @Override
    public void es2DownloadProfile(ES2DownloadProfileRequest parameters) {
         try {
            LOG.info("\n\n\n TEST BEAN: " + mock.callSoapClient() + "\n\n");
          }
     }  
}

Test class:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class ES2SmDpApplicationTests {

    @MockBean
    IMockWS mockService; //Again, you are mocking the interface, not the implementing class

    @Test
    public void test1Es2DownloadProfile_Sucess() throws MalformedURLException, JAXBException, SOAPException {
        when(mockService.callSoapClient()).thenReturn("CallMockCLient");
    }
}

Upvotes: 0

Related Questions