待测方法
protected override async Task<Name> DoExecuteAsync(NameContext context)
{
context.ThrowIfNull("context");
var request = new Request
{
Id = context.Id,
Principal = context.UserPrincipal,
};
return await this.repository.NameAsync(request, new CancellationToken(), context.ControllerContext.CreateLoggingContext());
}
protected override Name HandleError(NameContext viewContext, Exception exception)
{
if (this.errorSignaller != null)
{
this.errorSignaller.SignalFromCurrentContext(exception);
}
return Name.Unknown;
}
这是
的实施public abstract class BaseQueryAsync<TInput, TOutput> : IQueryAsync<TInput, TOutput>
{
public async Task<TOutput> ExecuteAsync(TInput context)
{
try
{
return await this.DoExecuteAsync(context);
}
catch (Exception e)
{
return this.HandleError(context, e);
}
}
protected abstract Task<TOutput> DoExecuteAsync(TInput context);
protected virtual TOutput HandleError(TInput viewContext, Exception exception)
{
ExceptionDispatchInfo.Capture(exception).Throw();
}
}
测试用例如下所示
[SetUp]
public void Setup()
{
var httpContext = MvcMockHelpers.MockHttpContext(isAuthenticated: true);
this.controller = new Mock<Controller>();
this.controller.Object.SetMockControllerContext(httpContext.Object);
this.repoMock = new Mock<IRepository>();
this.errorSignaller = new Mock<IErrorSignaller>();
this.query = new NameQuery(this.repoMock.Object, this.errorSignaller.Object);
this.userPrinciple = new Mock<IPrincipal>();
this.context = new NameContext(this.controller.Object.ControllerContext, this.userPrinciple.Object);
}
[Test]
public async Task TestDoExecuteAsyncWhenRepositoryFails()
{
// Arrange
this.repoMock.Setup(
x => x.NameAsync(
It.IsAny<Request>(),
It.IsAny<CancellationToken>(),
It.IsAny<ILoggingContext>())).Throws<Exception>();
// Act
Func<Task<Name>> act = async () => await this.query.ExecuteAsync(this.context);
// Assert
act.ShouldNotThrow();
this.errorSignaller.Verify(s => s.SignalFromCurrentContext(It.IsAny<Exception>()), Times.Once);
}
要验证名称对象,当我在行
之前使用var result = await act()
时
this.errorSignaller.Verify(s => s.SignalFromCurrentContext(It.IsAny<Exception>()), Times.Once);
this.errorSignaller.Verify
失败,因为它的计数是2而不是1.我的目的是检查Name
对象以及下面的代码。
act.ShouldNotThrow();
this.errorSignaller.Verify(s => s.SignalFromCurrentContext(It.IsAny<Exception>()), Times.Once);
我知道如果我编写一个新的测试用例,我可以很容易地验证它,但是在这个测试中我有什么办法可以完全做到吗?
答案 0 :(得分:0)
如果您想测试结果,请使用:
名称结果=等待this.query.ExecuteAsync(this.context);
result.Should()BE(expectefResult);
确保将您的测试方法设为公共异步任务
答案 1 :(得分:-1)
您可以尝试使用
进行检查await query.ExecuteAsync(this.context);
或
this.query.ExecuteAsync(this.context).GetAwaiter().GetResult();
,如果是Func:
act.Invoke().GetAwaiter().GetResult();
答案 2 :(得分:-1)
为了能够验证名称,您需要在函数中设置它。
//...code removed for brevity
Name expectedName = Name.Unknown;
Name actualName = null;
// Act
Func<Task> act = async () => {
actualName = await this.query.ExecuteAsync(this.context);
};
// Assert
act.ShouldNotThrow();
actualName
.Should().NotBeNull()
.And.Be(expectedName);
//...rest of code
正如评论中已经提到的,act
是一个返回Task
的函数。
在等待其实现时,仍然需要调用函数本身。由于该函数返回一个Task,因此也需要等待它。
Func<Task<Name>> act = async () => await this.query.ExecuteAsync(this.context);
var name = await act();
与具有以下功能相同。
async Task<Name> act() {
return await this.query.ExecuteAsync(this.context);
}
你必须以同样的方式等待它
var name = await act();
唯一的区别是前一个例子在委托中具有该功能。
尽量避免将阻塞调用(例如.Result
)与async / await代码混合使用。这往往会导致死锁。