我有这样的系统

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。如果通过默认值,将抛出异常。

引发异常,但测试失败并显示此消息。


  讯息:Assert.Throws()
  
  预期失败:typeof(System.Exception)
  
  实际:(未引发异常)


测试永远不会

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);
}


参考Assert.ThrowsAsync

关于c# - 如果在SUT的另一部分抛出异常,则测试失败(异步流),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53516495/

10-12 00:08
查看更多