1

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

Tsvetoslav
  • 175
  • 2
  • 11

2 Answers2

0

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");
    }
}
Lorelorelore
  • 2,881
  • 6
  • 25
  • 32
  • Thank you for the share. I did exactly as you wrote but the object is still null. It's look that the problem might be causes from something else - Spring or something else. – Tsvetoslav Mar 20 '19 at 09:37
  • Are you still using `@MockBean(name="mockWS")`? I don't think that you need to give the name of the bean. Also maybe you have to check the position of `@SpringBootApplication` annotation, maybe you have an issue with the component scan. – Lorelorelore Mar 20 '19 at 09:45
  • I removed the name from @MockBean `@MockBean IMockWS mockService;`. Regarding `@SpringBootApplication`, it locates in the root of package – Tsvetoslav Mar 20 '19 at 10:02
0

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

hello_earth
  • 1,068
  • 1
  • 20
  • 31