【发布时间】:2018-02-16 05:22:27
【问题描述】:
待测方法
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);
我知道如果我写一个新的测试用例,我可以很容易地验证它,但是有什么方法我可以在这个测试中完全做到吗?
【问题讨论】:
-
它是一个Func,即一个函数。你调用它来得到结果。由于是异步函数,所以你使用
await,即var name=await act(); -
已经在调用await this.query.ExecuteAsync(this.context);,这就是为什么我能够验证act.ShouldNotThrow();我不想再调用它了,我的理解对吗?
-
@user3910075 你的理解有误。关于调用该函数的评论是准确的。您可能需要提供更多有关您正在尝试做的事情的背景信息。显示单元测试的minimal reproducible example。这似乎是XY problem。您要达到的最终目标是什么?
标签: c# unit-testing async-await nunit fluent-assertions