C# 具有多个预期类型的XUnit Assert.IsType()

C# 具有多个预期类型的XUnit Assert.IsType(),c#,unit-testing,.net-core,xunit.net,C#,Unit Testing,.net Core,Xunit.net,我需要检查三种可能的异常类型中的一种。如果抛出其中一个,测试应该成功完成。我正在使用[Theory]和[MemberData]来处理几个场景 [Theory] [MemberData(nameof(GetInvalidMimeMessages))] public async Task ProcessAsync_TestFail(MimeMessage message) { var stub = Mock.Of<IOptions<ScrapyardFilesOptions>

我需要检查三种可能的异常类型中的一种。如果抛出其中一个,测试应该成功完成。我正在使用
[Theory]
[MemberData]
来处理几个场景

[Theory]
[MemberData(nameof(GetInvalidMimeMessages))]
public async Task ProcessAsync_TestFail(MimeMessage message)
{
    var stub = Mock.Of<IOptions<ScrapyardFilesOptions>>(s => s.Value.ConnectionString == "UseDevelopmentStorage=true" && s.Value.Container == "exchange");
    var loggerMock = new Mock<ILogger<ScrapyardFilesHandler>>(MockBehavior.Loose);
    var scrapyard = new ScrapyardFilesHandler(loggerMock.Object, stub);
    var ex = await Assert.ThrowsAnyAsync<Exception>(() => scrapyard.ProcessAsync(message));

    // imagine solution somehow like that
    Assert.IsType( 
                    { 
                      typeof(NullReferenceException)    ||
                      typeof(KeyNotFoundException)      ||
                      typeof(InvalidOperationException) ||
                    },
                    ex); 
}

private static IEnumerable<object[]> GetInvalidMimeMessages()
{
    yield return new object[] { null };
    yield return new object[] { new MimeMessage() };
    yield return new object[]
    {
        new MimeMessage(
            new List<InternetAddress>(),
            new InternetAddressList() { new MailboxAddress("ExchangeScrapyard@ol.su"), new MailboxAddress("exchange+scrapyard@Olex.su"), },
            string.Empty,
            MimeEntity.Load(ParserOptions.Default, Stream.Null))
    };
    yield return new object[]
    {
        new MimeMessage(
            new List<InternetAddress>(),
            new InternetAddressList() { new MailboxAddress("ExchangeOLC449@ol.su"), new MailboxAddress("exchange+olc@Ol.su"), },
            string.Empty,
            MimeEntity.Load(ParserOptions.Default, Stream.Null))
    };
}
[理论]
[成员数据(名称(GetInvalidMimeMessages))]
公共异步任务进程异步测试失败(MimeMessage消息)
{
var stub=Mock.Of(s=>s.Value.ConnectionString==“UseDevelopmentStorage=true”&&s.Value.Container==“exchange”);
var loggerMock=newmock(MockBehavior.Loose);
var scrapyard=新的ScrapyardFileHandler(loggerLock.Object,存根);
var ex=await Assert.ThrowsAnyAsync(()=>scrapyard.ProcessAsync(message));
//想象一下这样的解决方案
Assert.IsType(
{ 
typeof(NullReferenceException)||
类型(KeyNotFoundException)||
类型(无效操作例外)||
},
ex);
}
私有静态IEnumerable GetInvalidMimeMessages()
{
产生返回新对象[]{null};
产生返回新对象[]{new mimessage()};
返回新对象[]
{
新消息(
新列表(),
new InternetAddressList(){new MailboxAddress(“ExchangeScrapyard@ol.su),新邮箱地址(“exchange+scrapyard@Olex.su"), },
字符串。空,
MimeEntity.Load(ParserOptions.Default,Stream.Null))
};
返回新对象[]
{
新消息(
新列表(),
new InternetAddressList(){new MailboxAddress(“ExchangeOLC449@ol.su),新邮箱地址(“exchange+olc@Ol.su"), },
字符串。空,
MimeEntity.Load(ParserOptions.Default,Stream.Null))
};
}

我怎样才能得到这样的断言

由于要抛出多个可能的异常,NUnit中没有内置的方法来检查这一点。如果您只遇到一个例外情况,您可以使用:

Assert.Throws<NullReferenceException>(() => DoSomething);

由于要抛出多个可能的异常,NUnit中没有内置的方法来检查这一点。如果您只遇到一个例外情况,您可以使用:

Assert.Throws<NullReferenceException>(() => DoSomething);
var异常=新列表()
{
类型(NullReferenceException),
类型(KeyNotFoundException),
类型(无效操作例外),
};
var ex=await Assert.ThrowsAnyAsync(()=>foo.Bar());
Assert.Contains(例如GetType(),异常);
var异常=新列表()
{
类型(NullReferenceException),
类型(KeyNotFoundException),
类型(无效操作例外),
};
var ex=await Assert.ThrowsAnyAsync(()=>foo.Bar());
Assert.Contains(例如GetType(),异常);

为什么不使用
Assert.Throws呢?为什么一个操作和一个输入会导致多个异常?一条消息应该在一个异常中返回,因为现在您将多条消息传递到测试中,但您不知道是哪条消息引发了哪一个异常。@CodeCaster不确定我是否正确地找到了您,但是我不应该知道哪个消息抛出了哪个异常(实际上我已经知道了)是的,你应该。您传递了四条不同的消息,并期望出现三种不同的异常。您需要知道哪个消息导致哪个异常。如果null消息引发InvalidOperationException怎么办?这是否意味着您的代码工作正常?为什么不改用
Assert.Throws
?为什么一个操作和一个输入会导致多个异常?一条消息应该在一个异常中返回,因为现在您将多条消息传递到测试中,但您不知道哪条消息引发了哪种异常。@CodeCaster不确定我是否正确理解您,但我不应该知道哪条消息引发了哪种异常(实际上我已经知道了)是的,您应该这样做。您传递了四条不同的消息,并期望出现三种不同的异常。您需要知道哪个消息导致哪个异常。如果null消息引发InvalidOperationException怎么办?这是否意味着您的代码工作正常?感谢
Assert.Pass()。但我认为这已经足够好了,因为您不会从
NullReferenceException
或任何其他类型派生。您可以使用反射的
IsAssignable
IsSubClass
检查派生异常:有趣的解决方案,但只适用于确切的类型,而不适用于派生类型。但我认为这已经足够好了,因为您不会从
NullReferenceException
或任何其他派生。您可以使用反射的
IsAssignable
IsubClass
检查派生的异常:
var exceptions = new List<Type>()
            {
                typeof(NullReferenceException),
                typeof(KeyNotFoundException),
                typeof(InvalidOperationException),
            };

var ex = await Assert.ThrowsAnyAsync<Exception>(() => foo.Bar());
Assert.Contains(ex.GetType(), exceptions);