Issue
I have a problem about writing junit test for this service shown below. I wrote some methods but only one cannot work.
How can I fix it?
Here is the service shown below.
public class AmazonStoreService {
private final AmazonS3 amazonS3;
private final String BUCKET_NAME = "bucketname";
private String baseUrl ="baseUrl";
public String uploadImg(File file, Long id) {
amazonS3.putObject(BUCKET_NAME, id.toString(), file);
return baseUrl + bookId;
}
public void deleteImg(Long id) {
amazonS3.deleteObject(BUCKET_NAME, id.toString());
}
public String getImgUrl(Long id) {
return baseUrl + id;
}
}
Here is the AmazonServiceTest class shown below.
class AmazonServiceTest extends BaseServiceTest{
@InjectMocks
AmazonStoreService imageStoreService;
@Mock
AmazonS3 amazonS3;
private final String BUCKET_NAME = "bucketname";
private String baseUrl = "baseUrl";
@Test
void givenBookIdAndFile_thenReturnBaseUrlOfImage() {
// given - precondition or setup
Long bookId = 1L;
String fileName = "sample.png";
MockMultipartFile uploadFile =
new MockMultipartFile("file", fileName, "image/png", "Some bytes".getBytes());
File file = convert(uploadFile);
// when - action or the behaviour that we are going test
doNothing().when(amazonS3).putObject(BUCKET_NAME,bookId.toString(), file);
// then - verify the output
imageStoreService.uploadImg(file,bookId);
verify(imageStoreService, times(1)).uploadImg(any(File.class), any(Long.class));
}
@Test
void givenBookId_thenDeleteImageOfBook() {
// given - precondition or setup
Long bookId = 1L;
// when - action or the behaviour that we are going test
doNothing().when(amazonS3).deleteObject(BUCKET_NAME,bookId.toString());
// then - verify the output
imageStoreService.deleteImg(1L);
verify(amazonS3, times(1)).deleteObject(BUCKET_NAME,bookId.toString());
}
@Test
void givenBookId_tenReturnBaseUrlOfImage() {
// given - precondition or setup
Long bookId = 1L;
String expected = baseUrl + bookId;
// when - action or the behaviour that we are going test
// then - verify the output
String result = imageStoreService.getImgUrl(1L);
assertEquals(expected, result);
}
private File convert(final MultipartFile multipartFile) {
// convert multipartFile to File
File file = new File(Objects.requireNonNull(multipartFile.getOriginalFilename()));
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(multipartFile.getBytes());
return file;
} catch (IOException e) {
throw new RuntimeException("Failed to convert multipartFile to File : " + e);
}
}
}
Here is the error throwing from first test method named givenBookIdAndFile_thenReturnBaseUrlOfImage
org.mockito.exceptions.base.MockitoException:
Only void methods can doNothing()!
Example of correct use of doNothing():
doNothing().
doThrow(new RuntimeException())
.when(mock).someVoidMethod();
Above means:
someVoidMethod() does nothing the 1st time but throws an exception the 2nd time is called
Solution
You can mock AmazonS3 object by writing something like this:
AmazonS3 mockObject;
@Before
public void setup() {
mockObject = Mockito.mock(AmazonS3.class);
doNothing().when(mockObject).putObject(anyString(), any());
doNothing().when(mockObject).deleteObject(anyString(), anyLong());
}
Also you would need to find a way to inject this mockObject into your AmazonStoreService class.
Another way to mock is to use MockAnnotation
@Mock AmazonS3 mockObject;
@Before
public void setup() {
MockitoAnnotations.openMocks(this)
doNothing().when(mockObject).putObject(anyString(), any());
doNothing().when(mockObject).deleteObject(anyString(), anyLong());
}
Answered By - amanshri93
Answer Checked By - Gilberto Lyons (JavaFixing Admin)