0

I have a requirement to test a SpringBoot application where I run the tests against the end point (for now, locally).

There is one call from a service to external service (s3), and I just need to mock this, so that we don't do a live call to s3 from our test.

I use Mockito for mocking.

The call stack:

Controller -service

                   -external service.

From my test, I just hit the end point url (localhost:8080/actions/domyjob)

This is my controller:

@RestController
@RequestMapping("/myjob")
public class MyController{

    @Autowired
    private MyService myService;

    @RequestMapping(path = "/doJobInMyService", method = POST)
    public void doJobInMyService(){
        myService.doMyJob()
    }

}

This is my service:

@Service
public class MyService {

    @Autowired
    private s3Client AmazonS3Client;

     doMyJob() {
    s3Client.putObject(new PutObjectRequest());
}
}

If you see, if I want to test the entire flow, by calling localhost:8080/myjob/doJobInMyService and just mock s3Client.putObject(new PutObjectRequest()), so that external calls to s3 is not done.

Tried this, but I had still no luck:

@ActiveProfiles("MyTestConfig")
@RunWith(SpringJUnit4ClassRunner.class)
public class MyTest extends BaseTest {
    @Autowired
    private AmazonS3Client amazonS3Client;

    @Test
    public void testMyResponse() {
        try {
            Mockito.when(amazonS3Client.putObject(anyObject())).thenReturn(new PutObjectResult());
            assertNotNull(getMyClient().doMyJob());
        } catch(Exception e) {

        }
    }
}

@Profile("MyTestConfig")
@Configuration
public class MyTestConfiguration {

    @Bean
    @Primary
    public AmazonS3Client amazonS3Client() {
        return Mockito.mock(AmazonS3Client.class);
    }
nbro
  • 15,395
  • 32
  • 113
  • 196
Diva
  • 151
  • 1
  • 3
  • 9
  • Use Mockito to create a mock of the client that calls the service. – duffymo May 05 '16 at 11:15
  • We just hit the endpoint of the application through tests. Not really sure how spring would inject the mocked client during testing and real client for application purpose. – Diva May 05 '16 at 11:21
  • I don't have Spring inject mocks when I test. I write JUnit tests and do the injection manually using ctor injection. No need for Spring there. – duffymo May 05 '16 at 11:23
  • Do you invoke the end point while doing so? An example would be great – Diva May 05 '16 at 11:29
  • No, I invoke the client and tell it to return what I know the endpoint would give me for that input. That's what mocking is. – duffymo May 05 '16 at 11:29
  • Could you share a sample test code? – Daniel Olszewski May 05 '16 at 11:30
  • http://stackoverflow.com/questions/19299513/spring-junit-how-to-mock-autowired-component-in-autowired-component can be a solution? – Dzmitry Prakapenka May 05 '16 at 12:03
  • Can't you add some test configuration that creates a MyService from Mockito.mock ? Or even an s3Client? With profiles you can further control the whole test/not test thing. – Florian Schaetz May 05 '16 at 12:03
  • Dzmitry - i think that's more of a unit test. But i will look into it in detail. – Diva May 05 '16 at 12:22
  • Florian-Profiling is something i was thinking. Any example where i can override the external client to use a mock via an integration test would be really great. – Diva May 05 '16 at 12:23

2 Answers2

2

Since Spring Boot 1.4.x, there is Mockito mocking of Spring beans natively supported via annotation @MockBean. See this section of Spring Boot docs for more info.

luboskrnac
  • 23,973
  • 10
  • 81
  • 92
0

I created blog post on the topic. It contains also link to Github repository with working example.

The trick is using test configuration, where you override original spring bean (e.g. s3Client in your case) with fake one. You can use @Primary and @Profile annotations for this trick.

luboskrnac
  • 23,973
  • 10
  • 81
  • 92