Visual Studio 单元测试中的预期异常属性限制

Expected exception attribute limitation in Visual Studio Unit Test

我必须为将枚举映射到另一个枚举的现有方法编写单元测试。这个单元测试关注的是当方法中没有定义映射时的场景,我们在switch语句的default块中得到了一个异常。

enum players{sachin, ponting, mculum, gayle}
enum teams{westindies, australia, india, newzealand, southafrica}

public teams MappingMethod(players p)
{
  switch(p)
  {
    case sachin: return india;
    case gayle: return westindies;
    ......
    default: throw new ArgumentOutOfRangeException();
  }
}

我尝试了带有 ExpectedException 属性的单元测试,当遇到上述情况时,单元测试运行良好。但是当枚举中的所有项目都存在映射时它会失败。

为了解决这个问题,我在单元测试中使用了一个 try..catch 块,并使用 Assert.IsInstanceOfType 检查异常,而不是使用 ExpectedException 属性。

还有其他更好的方法来进行此单元测试吗?

看来您想要实现的是一种确保第一个枚举中的每个项目都应对应于另一个枚举中的项目的方法。也就是说,您希望 MappingMethod 始终成功。如果是这种情况,那么我可能建议您根本不需要 ExpectedException。编写一个遍历 Players 中所有元素并为每个元素调用 MappingMethod 的测试怎么样?如果有任何未映射的玩家,此测试将失败。

除此之外,您还可以编写一个测试来检查当您获得无效数据时是否抛出了预期的异常。像这样:

[TestMethod]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public void Throw_Exception_When_Mapping_Does_Not_Exist() {
    MappingMethod((Players)-1);
}

对这个确切的代码持保留态度 - 如果我没记错的话,((Players)-1) 会给你一个 Players 类型的对象,它不对应于实际中的任何元素枚举(当然,除非你已经分配了这样一个值)。这样,调用MappingMethod肯定会失败。

顺便说一句,我想补充一点,我不确定在你的情况下使用枚举是否合适。通常,当枚举迫使您使用某些 switch 语句时,这是一种代码味道,您应该考虑将枚举更改为 class。枚举通常用于表示简单的静态和有限数据。我怀疑 Players 应该是 class 而不是枚举。考虑这样的结构:

class Player {
    public Teams Team { get; private set; }
    public string Name { get; private set; }

    public Player(string Name, Teams team) { /* set properties */ }
}

那么你就会有一个球员sachin = new Player("Sachin", Teams.India)。这确保每个玩家都与一个团队相关联。此外,它更加动态,因为您可以稍后添加更多玩家,并且可以为每个玩家添加更多统计数据等。

希望对您有所帮助。祝你有美好的一天:)