MSTest单元测试独立运行通过,但在运行其他测试时失败

6

我在一些MSTest单元测试中遇到了问题,当我单独运行它们时,它们通过了测试,但是当我运行整个单元测试类时,它们失败了。这些测试用例测试了一些代码,SLaks先前帮助过我,他警告我我所做的不是线程安全的。然而,现在我的代码更加复杂,我不知道如何使其线程安全。以下是我的代码:

public static class DLLConfig
{
    private static string _domain;

    public static string Domain
    {
        get
        {
            return _domain = AlwaysReadFromFile
                ? readCredentialFromFile(DOMAIN_TAG)
                : _domain ?? readCredentialFromFile(DOMAIN_TAG);
        }
    }
}

我的测试很简单:

string expected = "the value I know exists in the file";
string actual = DLLConfig.Domain;
Assert.AreEqual(expected, actual);

当我单独运行此测试时,它通过了。但是当我将它与测试类中的所有其他测试一起运行时(这些测试对不同的属性执行类似的检查),actualnull,测试失败了。我注意到这不是一个自定义Enum类型属性的问题;也许我之所以遇到Domain属性的问题是因为它是一个string类型?或者这是MSTest工作方式的多线程问题?

你在测试之间如何设置/拆除环境? - Paddyslacker
@Paddyslacker:完全没有。我没有[TestCleanup][TestInitialize]方法。 - Sarah Vessels
1
好的单元测试应该是独立的,因此我建议通过添加一些设置和拆卸来使这些测试成为真正的单元测试,以便每次都将代码置于已知状态。如果有一个真正的测试用例需要同时调用方法或者调用两次方法,那么请编写一个特定的失败测试用例,然后使其通过。 - Paddyslacker
4个回答

6

我怀疑其他的测试修改了DLLConfig类中的某个值,导致getter方法返回结果发生了变化。单元测试应该从一个已知的初始状态开始运行,所以你应该在测试方法本身或者被标记为TestInitialize属性的方法中设置这个状态,在每个测试执行前运行。


5

你的测试依赖于外部文件。与其直接调用访问该文件的函数,你应该让DLLConfig.Domain调用另一个类中的方法。

public static string Domain
{
    get
    {
        return _domain = AlwaysReadFromFile
            ? CredentialReader.Read(DOMAIN_TAG)
            : _domain ?? CredentialReader.Read(DOMAIN_TAG);
    }
}

然后,您可以使用模拟/伪造/存根CredentialReader初始化DllConfig,以便您可以控制其返回值。请记住,您正在测试DLLConfig.Domain是否基于AlwaysReadFromFile条件返回正确的值。您不应该同时测试该值来自何处(或者它是否存在)。

使您的DLLConfig类更具“可测试性”还有一个额外的好处,即分离关注点。当您考虑一个类时,不能帮助但说“这个类做了这个那个”(抽象配置数据并从文件中读取该数据)时,它很可能是混合关注点并尝试做太多事情。如果DLLConfig是配置数据的抽象,则应仅专注于此,并将数据来源留给另一个类。


1
如果以上答案都无法解决您的问题,我通过在失败的测试中的断言之前添加Thread.Sleep(1)来解决了此问题...看起来测试同步在某个地方丢失了...请注意,我的测试不依赖于顺序,并且我没有任何静态成员或外部依赖项。

我花了整整一天的工作时间来寻找解决方案。非常感谢,这个完美地解决了问题! - wrager

0

对我来说,问题在于使用了一个非线程安全的集合。当我改用 BlockingCollection(而不是 List)时,一切都顺利解决了。


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