使用XUnit断言异常

wan*_*onk 82 c# unit-testing xunit

我是XUnit和Moq的新手.我有一个方法,它将字符串作为参数.如何使用XUnit处理异常.

[Fact]
public void ProfileRepository_GetSettingsForUserIDWithInvalidArguments_ThrowsArgumentException() {
    //arrange
    ProfileRepository profiles = new ProfileRepository();
    //act
    var result = profiles.GetSettingsForUserID("");
    //assert
    //The below statement is not working as expected.
    Assert.Throws<ArgumentException>(() => profiles.GetSettingsForUserID(""));
}
Run Code Online (Sandbox Code Playgroud)

正在测试的方法

public IEnumerable<Setting> GetSettingsForUserID(string userid)
{            
    if (string.IsNullOrWhiteSpace(userid)) throw new ArgumentException("User Id Cannot be null");
    var s = profiles.Where(e => e.UserID == userid).SelectMany(e => e.Settings);
    return s;
}
Run Code Online (Sandbox Code Playgroud)

Nko*_*osi 139

Assert.Throws表达式将捕获异常,并断言类型.但是,您正在调用断言表达式之外的测试方法,从而使测试用例失败.

[Fact]
public void ProfileRepository_GetSettingsForUserIDWithInvalidArguments_ThrowsArgumentException()
{
    //arrange
    ProfileRepository profiles = new ProfileRepository();
    // act & assert
    Assert.Throws<ArgumentException>(() => profiles.GetSettingsForUserID(""));
}
Run Code Online (Sandbox Code Playgroud)

如果遵循AAA,你可以将动作提取到它自己的变量中

[Fact]
public void ProfileRepository_GetSettingsForUserIDWithInvalidArguments_ThrowsArgumentException()
{
    //arrange
    ProfileRepository profiles = new ProfileRepository();
    //act
    Action act = () => profiles.GetSettingsForUserID("");
    //assert
    var exception = Assert.Throws<ArgumentException>(act);
    //The thrown exception can be used for even more detailed assertions.
    Assert.Equal("expected error message here", exception.Message);
}
Run Code Online (Sandbox Code Playgroud)

  • 实际上,对我来说导致错误的是,“无法将Task隐式转换为Func &lt;Task&gt;”,而如果我只是将`Task act()=&gt; service.DoTheThingAsync(); 等待Assert.ThrowsAsync &lt;InvalidOperationException&gt;(act);`然后对此感到满意并可以正常工作。 (4认同)

小智 42

如果您确实想要了解AAA,那么您可以使用xUnit中的Record.Exception来捕获Act阶段中的Exception.

然后,您可以根据Assert阶段中捕获的异常进行断言.

xUnits测试中可以看到这方面的一个例子.

__PRE__

这取决于您想要遵循的路径,xUnit提供的路径完全支持这两条路径.

  • @JeffLaFay,我很高兴我参加聚会有点晚了,这与使用 `var exception = Assert.Throws&lt;InvalidOperationException&gt;(testCode);` 和在 `exception.Message` 上断言有何不同?或者这只是实现同样目标的另一种方式? (2认同)
  • 如果您需要断言抛出异常,但您不想或不能具体说明异常的类型,那么这是一个很好的解决方案。 (2认同)

Yve*_*hon 9

如果你想坚持 AAA,你可以考虑这样的事情:

// Act 
Task act() => handler.Handle(request);

// Assert
await Assert.ThrowsAsync<MyExpectedException>(act);
Run Code Online (Sandbox Code Playgroud)