Родинки не работают в статических конструкторах - PullRequest
1 голос
/ 01 июля 2011

У меня возникла проблема с типами 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");
    }

... Теперь родинки больше не работают. При запуске этого теста я получаю сообщение об ошибке «Не удалось найти файл« d: \ blah \ blah \ test.txt »». Я понял это, потому что Moles больше не отвечает за мой класс FileSystem, поэтому модульный тест вызывает исходную реализацию, которая ищет файл в файловой системе.

Итак, единственное изменение состоит в том, что класс, из которого вызывается метод Moled, теперь является статическим. Я не изменил класс или метод Moled, они по-прежнему являются типами экземпляров, поэтому я не могу использовать Implement.Moles.SFileSystem. синтаксис, как это было бы для насмешки статического класса.

Может кто-нибудь помочь объяснить, как я могу заставить Молей работать внутри статического метода / конструктора?

Большое спасибо !!!

Ответы [ 2 ]

4 голосов
/ 01 июля 2011

Статический конструктор отличается от статического метода. С помощью метода вы можете контролировать, когда и где он вызывается. Конструктор автоматически вызывается средой выполнения перед выполнением любого доступа к классу, что в этом случае приводит к тому, что конструктор вызывается до установки крота для 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;
        }
    }
}

<ч /> Обновление:

Однако, если вы не можете изменить свою реализацию, единственная альтернатива, которую предлагает Moles, - это предотвратить выполнение кода в статическом конструкторе, а затем напрямую вычислить свойство Content. Чтобы удалить статический конструктор для типа, вам нужно включить в тестовую сборку следующий атрибут уровня сборки:

[assembly: MolesEraseStaticConstructor(typeof(StaticTestReader))]
0 голосов
/ 04 июля 2011

Я думаю, вам нужно удалить AllInstances из вашей декларации. Для доступа к статике вам не нужен экземпляр класса.

попробуйте это:

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