如果在 SUT 的另一部分(异步流)中抛出异常,则测试失败
Test fails if an Exception is thrown in another part of the SUT (async flow)
我有这样的系统
class Sut
{
IRepository _repo;
public Sut(IRepository repo) { _repo = repo; }
async Task Handle(Request request)
{
var entity = new Entity(request.Id); //=> if Id is not ok the Entity throws Exception
_repo.Save(entity);
}
}
这是测试
[Fact]
public async Task Test_Save()
{
Mock<IRepository> repositoryMock = new Mock<IRepository>();
repositoryMock
.Setup(repo => repo.Save(It.IsAny<Entity>()))
.Returns(Task.CompletedTask);
var sut = new Sut(repositoryMock.Object);
/// Act
Action action = async () => await sut.Handle(new Request { Id = default(Guid)});
/// Assert
Assert.Throws<Exception>(action);
repositoryMock.Verify(repo => repo.Save(It.IsAny<Entity>(), Times.Never);
}
所以它所做的是,Entity
检查传递给它的默认值 Guid
。如果传递默认值,它将抛出异常。
抛出异常但测试失败并显示此消息。
Message: Assert.Throws()
Failure Expected: typeof(System.Exception)
Actual: (No exception was thrown)
测试从不调用
repositoryMock.Verify(repo => repo.Save(It.IsAny<Entity>(), Times.Never);
它会在这一行中断
这是为什么以及如何解决这种情况?
Assert.Throws<Exception>(action);
更新
public Entity(Guid id)
{
if (default(Guid) == id) throw new Exception("cannot have a default value for id");
Id = id;
}
Action action = async () => ...
基本上是一个 async void
,这意味着抛出的异常不会被捕获。
更改语法以使用 Func<Task>
和 Assert.ThrowsAsync
[Fact]
public async Task Test_Save() {
//Arrange
var repositoryMock = new Mock<IRepository>();
repositoryMock
.Setup(repo => repo.Save(It.IsAny<Entity>()))
.Returns(Task.CompletedTask);
var sut = new Sut(repositoryMock.Object);
/// Act
AsyncTestDelegate act = () => sut.Handle(new Request { Id = default(Guid)});
/// Assert
await Assert.ThrowsAsync<Exception>(act);
repositoryMock.Verify(repo => repo.Save(It.IsAny<Entity>(), Times.Never);
}
我有这样的系统
class Sut
{
IRepository _repo;
public Sut(IRepository repo) { _repo = repo; }
async Task Handle(Request request)
{
var entity = new Entity(request.Id); //=> if Id is not ok the Entity throws Exception
_repo.Save(entity);
}
}
这是测试
[Fact]
public async Task Test_Save()
{
Mock<IRepository> repositoryMock = new Mock<IRepository>();
repositoryMock
.Setup(repo => repo.Save(It.IsAny<Entity>()))
.Returns(Task.CompletedTask);
var sut = new Sut(repositoryMock.Object);
/// Act
Action action = async () => await sut.Handle(new Request { Id = default(Guid)});
/// Assert
Assert.Throws<Exception>(action);
repositoryMock.Verify(repo => repo.Save(It.IsAny<Entity>(), Times.Never);
}
所以它所做的是,Entity
检查传递给它的默认值 Guid
。如果传递默认值,它将抛出异常。
抛出异常但测试失败并显示此消息。
Message: Assert.Throws()
Failure Expected: typeof(System.Exception)
Actual: (No exception was thrown)
测试从不调用
repositoryMock.Verify(repo => repo.Save(It.IsAny<Entity>(), Times.Never);
它会在这一行中断
这是为什么以及如何解决这种情况?
Assert.Throws<Exception>(action);
更新
public Entity(Guid id)
{
if (default(Guid) == id) throw new Exception("cannot have a default value for id");
Id = id;
}
Action action = async () => ...
基本上是一个 async void
,这意味着抛出的异常不会被捕获。
更改语法以使用 Func<Task>
和 Assert.ThrowsAsync
[Fact]
public async Task Test_Save() {
//Arrange
var repositoryMock = new Mock<IRepository>();
repositoryMock
.Setup(repo => repo.Save(It.IsAny<Entity>()))
.Returns(Task.CompletedTask);
var sut = new Sut(repositoryMock.Object);
/// Act
AsyncTestDelegate act = () => sut.Handle(new Request { Id = default(Guid)});
/// Assert
await Assert.ThrowsAsync<Exception>(act);
repositoryMock.Verify(repo => repo.Save(It.IsAny<Entity>(), Times.Never);
}