Moles 在静态构造函数中不起作用

发布于 2024-11-18 12:50:10 字数 2362 浏览 4 评论 0原文

我一直遇到 Mole 类型在静态构造函数中不起作用的问题。我创建了两个简单的示例来解释问题:

我有一个简单的实例类,如下所示:

public class InstanceTestReader
{
    public InstanceTestReader ()
    {
        IFileSystem fileSystem = new FileSystem();

        this.Content = fileSystem.ReadAllText("test.txt");
    }

    public string Content { get; private set; }
}

我对此有一个单元测试,如下所示:

    [TestMethod]
    [HostType("Moles")]
    public void CheckValidFileInstance_WithMoles()
    {
        // Arrange
        string expectedFileName = "test.txt";
        string content = "test text content";

        Implementation.Moles.MFileSystem.AllInstances.ReadAllTextString = (moledTarget, suppliedFilename) =>
        {
            Assert.AreEqual(suppliedFilename, expectedFileName, "The filename was incorrect");
            return content;
        };

        // Act
        string result = new InstanceTestReader().Content;

        // Assert
        Assert.AreEqual(content, result, "The result was incorrect");
    }

这没有问题。

但是,如果我将调用类更改为静态(不是 Moled 类,而是调用类),Moles 将不再起作用:

public static class StaticTestReader
{
    static StaticTestReader ()
    {
        IFileSystem fileSystem = new FileSystem();

        Content = fileSystem.ReadAllText("test.txt");
    }

    public static string Content { get; private set; }
}

并相应地修改我的单元测试:

    [TestMethod]
    [HostType("Moles")]
    public void CheckValidFileStatic_WithMoles()
    {
        // Arrange
        string expectedFileName = "test.txt";
        string content = "test text content";

        Implementation.Moles.MFileSystem.AllInstances.ReadAllTextString = (moledTarget, suppliedFilename) =>
        {
            Assert.AreEqual(suppliedFilename, expectedFileName, "The filename was incorrect");
            return content;
        };

        // Act
        string result = StaticTestReader.Content;

        // Assert
        Assert.AreEqual(content, result, "The result was incorrect");
    }

...现在 Moles 不再起作用。运行此测试时,我收到错误“找不到文件 'd:\blah\blah\test.txt'”。我之所以得到这个,是因为 Moles 不再负责我的 FileSystem 类,因此单元测试正在调用原始实现,该实现正在文件系统上查找文件。

因此,唯一的变化是调用 Moled 方法的类现在是静态的。我没有更改Moled类或方法,它们仍然是实例类型,所以我无法使用Implementation.Moles.SFileSystem 语法,因为这将用于模拟静态类。

请有人帮助解释我如何让 Moles 在静态方法/构造函数中工作?

非常感谢!

I have been having a problem with Mole types not working in static constructors. I have created two simple examples to explain the problem:

I have a simple instance class as follows:

public class InstanceTestReader
{
    public InstanceTestReader ()
    {
        IFileSystem fileSystem = new FileSystem();

        this.Content = fileSystem.ReadAllText("test.txt");
    }

    public string Content { get; private set; }
}

I have a unit test for this as follows:

    [TestMethod]
    [HostType("Moles")]
    public void CheckValidFileInstance_WithMoles()
    {
        // Arrange
        string expectedFileName = "test.txt";
        string content = "test text content";

        Implementation.Moles.MFileSystem.AllInstances.ReadAllTextString = (moledTarget, suppliedFilename) =>
        {
            Assert.AreEqual(suppliedFilename, expectedFileName, "The filename was incorrect");
            return content;
        };

        // Act
        string result = new InstanceTestReader().Content;

        // Assert
        Assert.AreEqual(content, result, "The result was incorrect");
    }

This works with no problems.

If I change my calling class to be static however (NOT the Moled class, but the calling class), Moles no longer works:

public static class StaticTestReader
{
    static StaticTestReader ()
    {
        IFileSystem fileSystem = new FileSystem();

        Content = fileSystem.ReadAllText("test.txt");
    }

    public static string Content { get; private set; }
}

And modify my unit test accordingly:

    [TestMethod]
    [HostType("Moles")]
    public void CheckValidFileStatic_WithMoles()
    {
        // Arrange
        string expectedFileName = "test.txt";
        string content = "test text content";

        Implementation.Moles.MFileSystem.AllInstances.ReadAllTextString = (moledTarget, suppliedFilename) =>
        {
            Assert.AreEqual(suppliedFilename, expectedFileName, "The filename was incorrect");
            return content;
        };

        // Act
        string result = StaticTestReader.Content;

        // Assert
        Assert.AreEqual(content, result, "The result was incorrect");
    }

... Now Moles no longer works. When running this test, I get the error "Could not find file 'd:\blah\blah\test.txt'". I get this because Moles is no longer in charge of my FileSystem class, so the unit test is calling the original implementation which is looking for a file on the file system.

So, the only change is that the class which the Moled method is called from is now static. I have not changed the Moled class or method, they are still instance types, so I cannot use the Implementation.Moles.SFileSystem
syntax as this would be for mocking a static class.

Please could someone help to explain how I can get Moles to work within a static method/constructor?

Many thanks!!!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

向日葵 2024-11-25 12:50:10

静态构造函数与静态方法不同。使用方法,您可以控制调用它的时间和地点。在执行对类的任何访问之前,运行时会自动调用构造函数,在这种情况下,会导致在设置 FileSystem 的摩尔之前调用构造函数,从而导致您看到的错误。

如果您将实现更改为如下所示,那么它应该可以工作。

public static class StaticTestReader
{
    private static string content;

    public static string Content
    {
        get
        {
            if (content == null)
            {
                IFileSystem fileSystem = new FileSystem();

                content = fileSystem.ReadAllText("test.txt");
            }

            return content;
        }
    }
}


Update:

但是,如果您无法更改实现,Moles 提供的唯一其他替代方案是阻止执行静态构造函数中的代码,然后直接摩尔 Content 属性。要删除类型的静态构造函数,您需要在测试程序集中包含以下程序集级别属性:

[assembly: MolesEraseStaticConstructor(typeof(StaticTestReader))]

A static constructor is different than a static method. With a method you have control of when and where its called. The constructor is automatically called by the runtime before any access to the class is performed which in this case leads to the constructor being called before the mole for the FileSystem is set up resulting in the error you are seeing.

If you change your implementation to something like the following then it should work.

public static class StaticTestReader
{
    private static string content;

    public static string Content
    {
        get
        {
            if (content == null)
            {
                IFileSystem fileSystem = new FileSystem();

                content = fileSystem.ReadAllText("test.txt");
            }

            return content;
        }
    }
}


Update:

However, if you cannot change your implementation the only other alternative that Moles offers is for you to prevent the code in the static constructor to be executed and then mole the Content property directly. To erase a static constructor for a type you need to include the following assembly level attribute in your test assembly:

[assembly: MolesEraseStaticConstructor(typeof(StaticTestReader))]
度的依靠╰つ 2024-11-25 12:50:10

我认为您必须从声明中删除 AllInstances 。要访问静态,您不需要类的实例。

试试这个:

Implementation.Moles.MFileSystem.ReadAllTextString = (...)

I think you have to remove the AllInstances from your declaration. To access the static you do not need an instance of a class.

try this:

Implementation.Moles.MFileSystem.ReadAllTextString = (...)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文