У меня есть проект библиотеки .NET с примерно 500 модульными тестами. Все эти тесты выполняются отлично в Visual Studio 2012. Однако некоторые из моих тестов не работают в Visual Studio 2010. В этих неудачных тестах я использую Moq, чтобы высмеять несколько типов Interop из Microsoft.Office.Interop.Excel
. При попытке получить доступ к этим издеваемым типам взаимодействия тест немедленно не выполняется:
Error: Missing method 'instance class Microsoft.Office.Interop.Excel.Range [ExcelAddIn.Core] Microsoft.Office.Interop.Excel.ListRow::get_Range()' from class 'Castle.Proxies.ListRowProxy'.
Это исключение подразумевает, что я забыл установить подходящее свойство getter на мой макет. Это не так:
_listRowMock.Setup(m => m.Range).Returns(_rangeMock.Object);
Теперь я могу представить, что Moq может не работать слишком хорошо с Interop Types. Но то, что я нахожу наиболее озадачивающим, заключается в том, что эти тесты отлично работают в Visual Studio 2012, но не работают в Visual Studio 2010.
Почему моя Visual Studio влияет на поведение моего кода?
ОБНОВЛЕНИЕ: 3-11-2012
Хорошо, поэтому я понял:
- У меня есть два проекта; Core и Core.UnitTest. Core - это фактическая библиотека, а Core.UnitTest - это проект unit test библиотеки Core.
- Оба проекта ссылаются на Microsoft.Office.Interop.Excel с включенными встроенными типами взаимодействия.
- Поскольку EIT включен, оба проекта включают в себя их собственное "представление" библиотеки Microsoft.Office.Interop.Excel. Представление включает все классы, методы и свойства, которые используются в их соответствующем проекте.
- Поскольку оба проекта используют разные классы, методы и свойства Microsoft.Office.Interop.Excel, встроенные типы обеих библиотек различаются. Например. ListRow в Core имеет свойство Index и Range, тогда как ListRow в Core.UnitTest имеет свойство Range.
- Хотя оба типа отличаются друг от друга и не имеют общего интерфейса или суперкласса, они эквивалент. Это означает, что CLR будет обрабатывать их, как если бы они были одинаковыми, и позволит вам использовать эти типы по границам сборки. Например. экземпляр ListRow из Core.UnitTest будет отлично работать при передаче методу в библиотеке Core. Свойство общего диапазона будет функционировать, в то время как недостающее свойство Index будет генерировать исключение MissingMethodException при доступе.
- Вышеупомянутое поведение даже работает с издеваемыми типами. Обманутый объект Mock [Excel.ListRow] отлично работает при пересечении границы сборки.
- К сожалению, поведение, описанное в предыдущем пункте, работает только тогда, когда я строю свои сборки в Visual Studio 2012. Когда я создаю свои сборки в Visual Studio 2010 и отлаживаю свой код, я могу увидеть, как посмеянный экземпляр ListRow передается в метод моего основного проекта. В тот момент, когда экземпляр пересекает границу сборки, все методы и свойства ListRow теряют свою реализацию и бросают MissingMethodExceptions.
- Теперь для забавной части мне действительно удалось смягчить эту проблему, убедившись, что оба встроенных типа ListRow выровнены. Например. чтобы компилятор мог создать тот же вид ListRow в обоих проектах, я убедился, что использовал те же самые методы и свойства в своем проекте UnitTest. Это означает добавление фиктивных строк, таких как: var dummy = listRow.Index. Как только у меня появился компилятор, создающий идентичные представления моего встроенного типа ListRow, экземпляру разрешалось пересекать границы сборки, не теряя при этом своей реализации.
Вопрос по-прежнему сохраняется: что вызывает эту разницу в поведении между Visual Studio 2010 и Visual Studio 2012?
ОБНОВЛЕНИЕ: 9-11-2012
Демо-решение: http://temp-share.com/show/KdPf6066h
Я создал небольшое решение для демонстрации эффекта. Решение состоит из библиотеки и проекта UnitTest. Оба относятся к Microsoft.Office.Interop.Excel.Range с включенным EIT. Тест отлично работает в VS2012, но генерирует MissingMethodException в VS2010. Раскомментирование фиктивной строки в тесте заставит ее работать в VS2010.
ЗАКЛЮЧИТЕЛЬНОЕ ОБНОВЛЕНИЕ: 29-12-2012
Мои извинения за последнее обновление. Мой коллега нашел решение, однако я не смог воспроизвести его на своей машине. Тем временем наша компания сделала переход на TFS2012, так что это уже не проблема блокировки для меня. Два самых важных вывода, сделанных моим коллегой:
- Семантика платформы "Любой процессор" изменилась с Visual Studio 2010 в Visual Studio 2012. Это приведет к .DLL создается в зависимости от того, используете ли вы VS2010 или VS2012.
- Оба проекта ссылаются на разные версии Microsoft.Office.Interop.Excel.
Я проверил свои проекты и выпрямил ссылки, но это не имело никакого значения. После этого я пробовал различные варианты платформ как в VS2010, так и VS2012, но не смог добиться удовлетворительного результата. Я отвечу на ответ Джереми, поскольку он был самым полезным. Спасибо всем за помощь.