[英]Non-void method with doNothing() in Mockito?
我有一個單元測試,用於測試將文件上傳到GCP存儲。 這是上傳文件的代碼。
@Override
public boolean upload(StorageConfiguration storageConfiguration, File file) throws MetaFeedException {
// get google storage connection.
Optional<Storage> storage = getStorageConnection(storageConfiguration.getJsonCredentialFilePath());
// if GCP storage is empty, return empty.
if (!storage.isPresent()) {
throw new MetaFeedException("Failed to establish connection with GCP storage");
}
// upload blob with given file content
BlobId blobId = BlobId.of(storageConfiguration.getBucketName(),
storageConfiguration.getBucketPath().concat(file.getName()));
BlobInfo blobInfo = BlobInfo.newBuilder(blobId).setContentType(storageConfiguration.getContentType()).build();
try {
return storage.get().create(blobInfo, Files.readAllBytes(Paths.get(file.getAbsolutePath()))).exists();
} catch (Exception e) {
throw new MetaFeedException("Error occurred while uploading file.", e);
}
}
在單元測試中,我做了類似的事情,
@Test
public void should_upload_file_to_gcp_with_given_data() throws Exception {
File tempFile = File.createTempFile("file-name", "1");
StorageConfiguration storageConfiguration = new StorageConfiguration();
storageConfiguration.setBucketName("sample-bucket");
storageConfiguration.setBucketPath("ff/");
storageConfiguration.setJsonCredentialFilePath("json-credentials");
storageConfiguration.setContentType("text/plain");
StorageOptions defaultInstance = mock(StorageOptions.class);
Storage mockStorage = spy(Storage.class);
when(defaultInstance.getService()).thenReturn(mockStorage);
BlobId blobId = BlobId.of(storageConfiguration.getBucketName(), storageConfiguration.getBucketPath().concat(tempFile.getName()));
BlobInfo blobInfo = BlobInfo.newBuilder(blobId).setContentType(storageConfiguration.getContentType()).build();
doNothing().when(mockStorage).create(blobInfo, Files.readAllBytes(Paths.get(tempFile.getAbsolutePath())));
boolean upload = gcpStorageManager.upload(storageConfiguration, tempFile);
Assert.assertTrue(upload);
}
我正在嘗試做的是防止調用create()
方法。 我的觀點是,我不想將其真正上傳到GCP,因為這是一項測試。 所以我嘗試了如上所述。 但是我有一個錯誤
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
UPDATE
Optional<Storage> storage;
try {
//connect with the json key file if the key path is not empty
if (StringUtils.isNotEmpty(jsonCredentialFilePath) && Files.exists(Paths.get(jsonCredentialFilePath))) {
storage = Optional.ofNullable(StorageOptions.newBuilder()
.setCredentials(ServiceAccountCredentials.fromStream(new FileInputStream(jsonCredentialFilePath)))
.build().getService());
} else {
// if no json key file provided connect to storage without key file.
storage = Optional.ofNullable(StorageOptions.getDefaultInstance().getService());
}
} catch (Exception e) {
throw new MetaFeedException("Error occurred while connecting to GCP storage", e);
}
return storage;
有沒有辦法解決將文件上傳到GCP的測試?
錯誤消息中描述了實際的問題: Only void methods can doNothing()
create()
方法不是無效的,因此無法使用doNoting()
對其進行模擬,因此必須使用doReturn
來代替。 在這種情況下,您可以返回Blob
的模擬:
Blob mockBlob = mock(Blob.class);
when(mockBlob.exists()).thenReturn(true);
doReturn(mockBlob).when(mockStorage).create(blobInfo, Files.readAllBytes(Paths.get(tempFile.getAbsolutePath())));
這是第一個錯誤。 第二,看起來您沒有將間諜對象注入被測對象。 您的方法getStorageConnection()
會在您調用Storage
時創建一個新實例,並且不考慮間諜對象。 因此,您在StorageOptions.class
但是StorageOptions.getDefaultInstance()
方法對這個StorageOptions.getDefaultInstance()
對象一無所知。
因此,在這里我可以看到兩種解決問題的方法。 第一個,對我來說,更可取的是將依賴注入到方法或類中。 對方法的依賴注入:
@Override
public boolean upload(Storage storage, File file) throws MetaFeedException {
但是,事實並非如此,只要您的方法覆蓋了某些接口(如我所假設的那樣)。 因此,您可以將方法getStorageConnection
移至單獨的類StorageProvider
並將其實例注入您的類,然后在測試中可以模擬StorageProvider
以返回Storage
的spy
。 在上載方法中,您將調用:
Optional<Storage> storage = storageProvider.getStorageConnection(storageConfiguration.getJsonCredentialFilePath());
第二個路徑是解決方法,它是使方法getStorageConnection
受保護,並在測試中覆蓋它以返回一個受監視的對象。 在您的測試中:
gcpStorageManager = new GcpStorageManager() {
@Override
protected Storage getStorageConnection(...) {
return mockedStorage;
}
}
我有以下問題:我有一個返回Page <...>的方法,但是我只能在void方法上使用doNothing(),所以修復很容易:
@Override
public Page<ThreadServiceModel> findAll(Pageable pageable) {
return this.findAll(ThreadServiceModel.class, pageable);
}
現在我們開始:
//Will fail and the actualy findAll will be invoked:
when(this.threadServices.findAll(ThreadServiceModel.class,pageable)).thenReturn(null);
//Will fail ,cuz you cannot call doNothing() on something that returns values
doNothing().when(this.threadServices).findAll(ThreadServiceModel.class,pageable);
//This is the solution ,and when you use doReturn() the actual method will be NOT invoked,
//+In my case i dont need value , but if i want I cant use...
doReturn(null).when(this.threadServices).findAll(ThreadServiceModel.class,pageable);
所以解決方案很簡單,請在我向您展示的代碼上使用最后一種方法:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.