Microsoft родинки, динамически инструмент - PullRequest
6 голосов
/ 08 июня 2011

Родинки могут быть использованы двумя способами:

вручную

  1. Включая [сборка: MoledType (typeof (_type_to_instrument))]]
  2. Укажите [HostType ("Moles")]
  3. Вызовите Microsoft.Moles.Framework.Moles.MoleRuntime.SetMole (делегат _stub, объект _receiver, метод MethodInfo);

Динамически

  1. Добавить файл {имя проекта} .moles: указание сборки в моль. например <Moles xmlns="http://schemas.microsoft.com/moles/2010/"> <Assembly Name="Samples.Moles"/> </Moles>
  2. Сборка и включение ссылки на MolesAssemblies / {имя_проекта} .Moles.dll
  3. Используйте M {class_name} автоматически генерируемых классов моль.

Что я заметил, так это то, что для использования динамической сборки не требуется, чтобы тестовый проект объявлял атрибуты «moled Сборки». Это уменьшает накладные расходы, и разработчик должен только украшать каждый метод тестирования типом хоста для родинок; но дальнейшее тестирование не должно отслеживать, какие типы инструментов.

Глядя на автоматически сгенерированный код (с использованием дизассемблера) в кросс-сборках, легко найти необходимые атрибуты инструментария. Тем не менее, попытка написать собственную «сборку родинок», по сути, заменяющую автоматически сгенерированную, не работает, и среда выполнения жалуется, что мой тип требует инструментирования. Мне любопытно, чего мне не хватает.

Я заметил, что автоматически сгенерированный код родинок объявил необходимые атрибуты MoledAssembly. Но в моих тестах тестовый проект, кажется, должен объявить это свойство; это не может быть объявлено ссылкой сборкой на проект. Тем не менее, в случае с автоматически сгенерированной сборкой, он ПОЯВЛЯЕТСЯ, что атрибут может быть объявлен "снаружи". Это моё предположение, основанное на том, что я вижу при разборке автоматически сгенерированных родинок dll; Я не могу найти никакой другой разницы. Однако, как я пытаюсь объяснить, копирование всего кода (и атрибутов) из дизассемблированной автоматически созданной moles dll и сборка моей собственной сборки, на которую ссылаются, завершаются неудачно во время выполнения, говоря, что я не пометил необходимую сборку в тесте для инструментирования (т.е. помеченный MoledAssembly) - хотя он есть, просто в моей сборке.

- обновить

На данный момент (вероятно, из-за моего неправильного понимания того, чего не хватает в моем коде), я чувствую, что нам нужно быть очень конкретными относительно того, что в сборке есть, что. Допустим, у нас есть 4 dll:

  1. Test.dll: проект mstest. Не объявлено MoledAssembly.
  2. Moles.dll: автоматически сгенерированная dll, созданная при использовании файла *.moles в вашем проекте. Ссылка на 4-й DLL, (см. # 4) Sealed. Объявляет [assembly: MoledAssembly("Sealed")]. Обратите внимание, что я пытаюсь выполнить ручную инъекцию моли без этой DLL - это только концептуальная ссылка или будет использоваться в нашем обсуждении или устранении неполадок.
  3. MyMoles.dll: автоматически сгенерированная версия из моего исходного кода Moles.dll.
  4. Sealed.dll: содержит проверяемый код.

В ответах / комментариях / вопросах - давайте обратимся к каждой части в соответствии с этим списком.

1 Ответ

4 голосов
/ 09 июня 2011

Атрибут сборки требуется при использовании смоделированных сборок, которые не создаются автоматически. Инструменты Moles для Visual Studio автоматически предупреждают компилятор о наличии сгенерированных сборок по необходимости.

При добавлении сборки кротов через Visual Studio сборка кротов не создается до тех пор, пока не будет построен проект. Кроме того, невозможно включить атрибут сборки для сборки, которая еще не существует. Это приведет к сбою компилятора. Следовательно, Moles также необходимо динамически добавлять команды в командную строку компилятора, генерировать смоделированные сборки и затем правильно ссылаться на них из проекта.

При использовании сгенерированной вручную сборочной сборки необходимо включить атрибут сборки, поскольку инструментам Moles не известно о его наличии, поскольку сборка не создается автоматически. Программист должен выполнить работу для родинок.

Если вы хотите пойти дальше, вы можете использовать генерацию кода до того, как компилятор включится. PERL может легко ввести необходимый атрибут сборки, где это необходимо. Когда компилятор получит код, ему уже будут вставлены атрибуты.

Эксперимент в поддержку моего ответа:

Мне удалось воспроизвести вашу проблему. Я также смог решить проблему, добавив атрибут сборки ниже , используя блок операторов . Для создания примера приложения я предпринял следующие шаги:

  1. Создан проект библиотеки классов .NET 4.0 C # с именем ClassLibrary2.
  2. Создан следующий метод, в Class1:

    публичная строка TestString () {return "Original value."; }

  3. Создал тестовый проект (TestProject1), щелкнув правой кнопкой мыши объявление метода TestString и выбрав Создать модульные тесты ... (Ленивый, я знаю.)

  4. Удалил лишнее дерьмо из Class1Test.cs, оставив TestStringTest ().
  5. Добавлена ​​сборка родинок для mscorlib. (Еще один ленивый ярлык и ненужный шаг, оглядываясь назад. Я отмечаю это здесь, потому что это то, что я сделал.)
  6. Добавлена ​​сборка родинок для ClassLibrary2.
  7. Скомпилированное решение с использованием профиля по умолчанию Любой профиль CPU .
  8. Использовал Redgate (извините, @payo) для декомпиляции ClassLibrary2.Moles
  9. Добавлен новый проект библиотеки классов с именем MoleClassLibrary.
  10. Скопировал декомпилированный код MClass1 и SClass1 в MoleClassLibrary.
  11. Удален файл Class1.moles и сборки из TestProject1.
  12. Удалил (ненужный) файл mscorlib.moles и сборки из TestProject1.
  13. Добавлена ​​ссылка MoleClassLibrary на TestProject1.
  14. Обновлен с использованием оператора в Class1Test.cs.
  15. Построить решение.
  16. Выполнено TestStringTest () с использованием Visual Studio 2010 Тестовое представление окно .
  17. Тест не пройден, подробности:

метод испытания TestProject1.Class1Test.TestStringTest бросил исключение: Microsoft.Moles.Framework.Moles.MoleNotInstrumentedException: System.String ClassLibrary1.Class1.TestString () был не инструментировано Чтобы решить эту проблему вопрос, добавьте следующий атрибут в тестовый проект:

с использованием Microsoft.Moles.Framework; [Сборка: MoledAssembly (TypeOf (ClassLibrary1.Class1))]

Я добавил рекомендованный атрибут сборки в файл. После этого метод испытания прошел успешно. Я подозреваю, что компилятор автоматически ссылается на сгенерированные смоделированные сборки, устраняя необходимость в атрибуте сборки. Я попытался скопировать двоичные файлы MoleClassLibrary в каталог MolesAssemblies и создать файл MoleClassLibrary.moles, чтобы проверить эту теорию. Тест прошел только тогда, когда я включил атрибут сборки. Этот результат не соответствует моей гипотезе.

Вот код для Class1Test.cs:

using ClassLibrary1;
using Microsoft.Moles.Framework;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MoleClassLibrary;
[assembly: MoledAssembly(typeof(ClassLibrary1.Class1))]

namespace TestProject1
{
    [TestClass()]
    public class Class1Test
    {
        [TestMethod()]
        [HostType("Moles")]
        public void TestStringTest()
        {
            var target = new Class1();
            var expected = "Mole value.";
            string actual;
            MClass1.AllInstances.TestString = value => expected;
            actual = target.TestString();
            Assert.AreEqual(expected, actual);
        }
    }
}
...