4

我不认为这是目前可能的,或者即使它是一个好主意,但这是我刚才在考虑的事情。我使用 MSTest 对我的 C# 项目进行单元测试。在我的一项测试中,我执行以下操作:

MyClass instance;

try
{
    instance = getValue();
}
catch (MyException ex)
{
    Assert.Fail("Caught MyException");
}

instance.doStuff(); // Use of unassigned local variable 'instance'

为了使这段代码编译,我必须instance在它的声明或catch块中分配一个值。我也可以return在之后,Assert.Fail但这仍然是一种解决方法,而不是编译器只知道在此之后执行无法继续。 Assert.Fail据我所知,永远不会允许执行超过它,因此instance永远不会在没有价值的情况下使用。那为什么我必须给它赋值呢?如果我将 更改为Assert.Failthrow ex代码编译得很好,我假设因为它知道异常将不允许执行继续到instance未初始化使用的点。

相反,如果我不想让测试失败,而是被标记为不确定怎么办?我可以做一个Assert.Inconclusive代替Fail,如果编译器知道在那之后执行将不会继续,那就太好了。

那么它是运行时与编译时关于允许执行在哪里进行的情况吗?对于 C# 来说,在这种情况下Assert.Fail,一个成员在返回后将永远不允许执行,这是否合理?也许这可能是方法属性的形式。这对编译器有用还是不必要的复杂性?

外部单元测试

由于人们[有效地]指出这是编写单元测试的一种愚蠢方式,因此请在单元测试领域之外考虑我的问题:

MyClass instance;

if (badThings)
{
    someMethodThatWillNeverReturn();
}
else
{
    instance = new MyClass();
}

instance.doStuff();

在这里,我可能会someMethodThatWillNeverReturn用抛出异常来替换调用,也许如果我有事情要做,我可以在异常的构造函数中完成它。

Resharper 知道

如果我在orreturn之后添加,Resharper 会将颜色变为灰色,并显示“代码无法通过启发式访问”的工具提示。Assert.FailAssert.Inconclusivereturn

4

5 回答 5

3

是的,有一些东西表明一个成员永远不会正常完成是合理的——即断言该成员之后的点是不可到达的。(这可能是由于异常或由于永远循环。)

如果你错了,你会希望有一些东西Assert.Fail(无论是在 CLR 中还是在编译器中)提出一个备份计划:如果有人更改为正常返回会发生什么?您可能希望部分代码验证是检查它永远不会正常返回的东西。

我相信微软的某个人有一篇关于这个想法的博客文章......我会看看我是否能找到它。

就表示它的语法而言,虽然属性是一个显而易见的想法,但我非常喜欢“从不”返回类型的想法。显然,这可能会与现有的“从不”类型发生冲突,但是嘿......

就其有用性而言:显而易见的解决方法是在语句之​​后立即抛出异常,但必须这样做肯定很烦人。(它通常比返回更好,因为这意味着如果您编写它的方法具有返回类型,您不必指定毫无意义的返回值 - 而且您也不需要确保所有out参数都是赋值。)所以它不是必需的- 但我认为它会很好。这是否是 C# 团队在有限预算下可以做的最重要的事情是另一回事 - 只是为了抢占 Eric ;)

于 2010-03-24T20:27:43.220 回答
1

throw ex之后Assert.Fail?或者,更好的是,在这种情况下完全删除try/catchand Assert.Fail,让未捕获的异常为您的单元测试失败。

于 2010-03-24T20:36:04.433 回答
1

我想知道的一件事是:如果您手动编译并执行此代码,运行时将如何处理它?我相信它会检查 IL 代码中的错误,也许它也会捕捉到这个“错误”......也许不是:)

于 2010-03-24T20:40:32.893 回答
0

returnAssert.Fail()

于 2010-03-24T20:26:51.203 回答
0

看到你在一个抛出的异常上断言失败,为什么不把整个测试移到try中,或者去掉try,让抛出的异常自动断言失败。

try
{
    MyClass instance;
    instance = MyClass.getValue();
    instance.doStuff();
}
catch (Exception ex)
{
    Assert.Fail("Caught MyException");
}

... 或者 ...

MyClass instance;
instance = MyClass.getValue();
instance.doStuff();
于 2010-03-24T20:37:38.413 回答