可空引用类型和MSTest ClassInitialize

9

MSTest提供了一个[ClassInitialize]属性,可以放置在一个static方法上,以提供一次性初始化。

假设我有一个测试类中的静态成员,我希望在这个 [ClassInitialize] 方法中进行初始化。如何标记它不可为空?

例如,考虑以下代码:

private static Database _database;

[ClassInitialize]
public static void InitializeClass(TestContext testContext)
{
    _database = new Database();
}

使用#nullable enable,我会得到一个非常易懂的警告:CS8618 在退出构造函数时,非可空字段“_database”必须包含非空值。考虑将该字段声明为可空。

我可以将初始化移动到构造函数中(但这样每个测试方法都会发生)。我可以使用null-forgiving operator(!)。是否有更好的选项来标记_database不为空?


1
如果预计 new Database() 永远不会失败,请考虑在静态构造函数中设置它。 - Rikki Gibson
1个回答

5

我更喜欢在这种情况下使用null forgiving。具体来说,您只需设置您知道将被填充的属性,但编译器无法使用null!

例如:

private static Database _database = null!;

我很惊讶这是有效的代码。如果你只是在说编译器错了,那么为什么不通过#pragma禁用警告呢? - Haighstrom
我认为使用pragma或其他系统来管理这种问题存在两个问题。第一个是你实际上需要在代码中包含注释来禁用它,如果你正在尝试编写自文档化的代码并最小化注释,这可能会使事情变得混乱。另外一个问题是它适用于整个代码块,如果你有多行代码需要应用它,这可能是一种好处而不是缺点。 - Dylan Smith
这种语法更常见的使用场景是在.NET单元测试中。可以使用此类语法创建在多个测试中使用的属性,并在标有ClassInitialize的函数中进行赋值。由于它们未在构造函数中设置,因此您的IDE很可能会将其识别为错误。通过将值设置为null!,您实际上是告诉IDE相信您的决定。 - Dylan Smith
我将包括一个最后的例子,即在编写单元测试时可以使用它来针对代码进行测试,当为参数提供null值时,该代码应该抛出ArgumentNullExceptions。 - Dylan Smith
2
我实际上是在寻找单元测试/TestInitialize时搜索并找到了这个答案。你的回复很有道理。我想知道是否可以添加一个额外的关键字或属性,以便为此取消警告。甚至允许感叹号出现在定义中?我已经实施了你的答案,但这个解决方案仍然感觉非常笨拙。 - Haighstrom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接