title: Mockito mocked method returns null
body: <p>I have what I think is a pretty standard StorageService that exists in a Spring Boot app for a web API.</p>
  
  <pre class="lang-java prettyprint-override"><code>@Component
  @Service
  @Slf4j
  public class StorageService {
      @Autowired
      private AmazonS3 s3Client;
  
      @Autowired
      private RestTemplate restTemplate;
  
      @Value("${app.aws.s3.bucket}")
      private String bucket;
  
      @Async
      public boolean fetchAndUpload(List&lt;URI&gt; uris) {
          List&lt;CompletableFuture&lt;PutObjectResult&gt;&gt; futures = uris.stream().map(uri -&gt;
                  fetchAsync(uri).thenApplyAsync((asset) -&gt; put(getName(uri.toString()), asset))
          ).collect(Collectors.toList());
  
          CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()])).join();
  
          return true;
      }
  
      @Async
      private CompletableFuture&lt;InputStream&gt; fetchAsync(URI uri) {
          return CompletableFuture.supplyAsync(() -&gt; {
              InputStream resp;
              try {
                  // asdf is null here when running my unit tests
                  Resource asdf = restTemplate.getForObject(uri, Resource.class);
                  resp = Objects.requireNonNull(asdf).getInputStream();
              } catch (IOException e) {
                  throw new RuntimeException(e);
              }
              return resp;
          });
      }
  
      private PutObjectResult put(String name, InputStream data) {
          PutObjectRequest request = new PutObjectRequest(bucket, name, data, new ObjectMetadata());
          return s3Client.putObject(request);
      }
  }
  </code></pre>
  
  <p>Here is an integration test, which at minimum successfully fetches the images given by the integration test:</p>
  
  <pre class="lang-java prettyprint-override"><code>@RunWith(SpringRunner.class)
  @SpringBootTest
  @AutoConfigureWebClient
  public class StorageServiceIT {
      @Value("${app.aws.s3.access.key}")
      private String accessKey;
  
      @Value("${app.aws.s3.secret.key")
      private String secretKey;
  
      @Spy
      private AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
              .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey, secretKey)))
              .withRegion(Regions.US_EAST_1)
              .build();
  
      @Spy
      private RestTemplate restTemplate = new RestTemplateBuilder().build();
  
      @MockBean
      private SignService signingService;
  
      @Autowired
      private StorageService storageService;
  
      @Before
      public void setUp() throws Exception {
          MockitoAnnotations.initMocks(this);
      }
  
      @Test
      public void fetchAsync() throws URISyntaxException {
          List&lt;URI&gt; uris = List.of(
                  new URI("https://upload.wikimedia.org/wikipedia/commons/e/ec/Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg"),
                  new URI("https://upload.wikimedia.org/wikipedia/commons/e/ec/Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg")
          );
  
          storageService.fetchAndUpload(uris);
      }
  }
  </code></pre>
  
  <p>However, the following unit test does not successfully mock the <code>restTemplate.getForObject</code> call, it constantly returns null, even when setting both arguments to <code>any()</code>. </p>
  
  <pre class="lang-java prettyprint-override"><code>@RunWith(SpringRunner.class)
  @SpringBootTest
  @AutoConfigureWebClient
  public class StorageServiceTest {
      @MockBean
      private AmazonS3 s3Client;
  
      @MockBean
      private RestTemplate restTemplate;
  
      @MockBean
      private SignService signingService;
  
      @Autowired
      // @InjectMocks ???
      private StorageService storageService;
  
      @Value("${app.aws.s3.bucket}")
      private String bucket;
  
      @Before
      public void setUp() throws Exception {
          MockitoAnnotations.initMocks(this);
      }
  
      List&lt;URI&gt; randomUris(int num) {
          final String base = "https://example.com/%s";
          return Stream.iterate(0, i -&gt; i)
                  .limit(num)
                  .map(o -&gt; URI.create(String.format(base, UUID.randomUUID().toString())))
                  .collect(Collectors.toList());
      }
  
      @Test
      public void fetchAsyncTest() {
          List&lt;URI&gt; uris = randomUris(2);
  
          uris.forEach(uri -&gt; {
              ByteArrayInputStream data = new ByteArrayInputStream(
                      Integer.toString(uri.hashCode()).getBytes());
              PutObjectRequest request = new PutObjectRequest(
                      bucket, getName(uri.toString()), data, new ObjectMetadata());
  
              Resource getResult = mock(Resource.class);
              try {
                  doReturn(data).when(getResult).getInputStream();
              } catch (IOException e) {
                  e.printStackTrace();
              }
  
              doReturn(data).when(restTemplate).getForObject(any(), any());
  
  //          none are working
  //          doReturn(data).when(restTemplate).getForObject(eq(uri), eq(Resource.class));
  //          doReturn(data).when(restTemplate).getForObject(uri, Resource.class);
  //          when(restTemplate.getForObject(uri, Resource.class)).thenReturn(data);
  //          when(restTemplate.getForObject(eq(uri), eq(Resource.class))).thenReturn(data);
  //          when(restTemplate.getForObject(any(), any())).thenReturn(data);
  
              PutObjectResult res = new PutObjectResult();
              doReturn(res).when(s3Client).putObject(eq(request));
  
  //            not working here as well, i think
  //            doReturn(res).when(s3Client).putObject(request);
  //            doReturn(res).when(s3Client).putObject(any());
  //            when(s3Client.putObject(eq(request))).thenReturn(res);
  //            when(s3Client.putObject(request)).thenReturn(res);
  //            when(s3Client.putObject(any())).thenReturn(res);
  
          });
  
          boolean res = storageService.fetchAndUpload(uris);
      }
  }
  </code></pre>
  
  <p>And just in case it's relevant, this is how I'm building the <code>RestTemplate</code>:</p>
  
  <pre class="lang-java prettyprint-override"><code>  @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
      return builder.build();
    }
  </code></pre>
  
  <p>I'm stumped, all advice is appreciated! :|</p>