我有async
个方法,它们没有任何返回类型,只有Task
类型。
如何为Task
编写有效的单元测试方法?
异步方法:
public async Task UploadFileAsync(FileDetails data)
{
await _fileUpload.UploadImageAsync(data);
}
public async Task UploadImageAsync(FileDetails data)
{
// does a async operation to upload a stream to azure blob storage
await azureBlob.UploadFromStreamAsync(streamData).ConfigureAwait(false)
}
测试方法:
[TestMethod]
public async Task UploadFileAsync()
{
//-->Arrange
_fileUpload.Setup(e => e.UploadImageAsync().Returns(new Task<Task>(() => null));
//-->Act
Task result = _uploadManager.UploadFileAsync(GetFakeUploadData());
// Task doesn't return any result ?
//-->Assert
}
更新
最后,我调用this方法将文件上传到azure blob存储区。
答案 0 :(得分:7)
您可以将“行为”部分更改为:
//-->Arrange
_fileUpload
.Setup(e => e.UploadImageAsync(It.IsAny<FileDetails>()))
.Returns(Task.FromResult<object>((object)null))
.Verifiable(); //<-- Allows you to verify that the mock was invoked correctly
//Act
await _uploadManager.UploadFileAsync(GetFakeUploadData());
//Assert
_fileUpload.Verify();
参考Moq Quickstart以更好地了解如何使用Moq框架。
答案 1 :(得分:2)
返回Task
的异步方法类似于常规void
方法。您可以等待任务以确保在测试完成之前运行该方法:
Task result = _uploadManager.UploadFileAsync(GetFakeUploadData());
await result.ConfigureAwait(false);
这里没有断言 - 你可以说的方法是它运行而不会触发错误。
如果服务器在上传完成时(例如,某些专有资源标识符)向您的应用程序返回一些令牌,那么更改UploadFileAsync
的签名以使该标识符对调用者可用是有益的:
public async Task<UploadedResourceIdentifier> UploadFileAsync(FileDetails data) {
var ret = await _fileUpload.UploadImageAsync(data).ConfigureAwait(false);
return new UploadedResourceIdentifier(ret); // Parses the return, and constructs resource identifier
}
现在测试将有一些东西要断言:
var result = await _uploadManager
.UploadFileAsync(GetFakeUploadData())
.ConfigureAwait(false);
Assert.That(result.IsValid, Is.True);
答案 2 :(得分:0)
我建议您使用ContinueWith
方法,以便检查IsFaulted
成员。
result.ContinueWith(t => Assert.IsFalse(t.IsFaulted));
答案 3 :(得分:0)
await _uploadManager.UploadFileAsync(GetFakeUploadData());
执行操作并等待它完成,然后你应该以某种方式访问上传的文件并在那里验证它。如果您可以上传,也可以下载,所以请使用它。