У меня есть проект библиотеки .NET с примерно 500 модульными тестами. Все эти тесты работают нормально в Visual Studio 2012. Однако некоторые из моих тестов не проходят в Visual Studio 2010. В этих неудачных тестах я использую Moq для имитации нескольких типов взаимодействия из 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'.
Это исключение означает, что я забыл настроить соответствующий метод получения свойств на моем макете. Что не так:
_listRowMock.Setup(m => m.Range).Returns(_rangeMock.Object);
Теперь я могу представить, что Moq может не слишком хорошо работать с Interop Types. Но что меня больше всего озадачивает, так это то, что эти тесты работают нормально в Visual Studio 2012, но не работают в Visual Studio 2010.
Почему моя Visual Studio влияет на поведение моего кода?
ОБНОВЛЕНИЕ: 3 ноября 2012 г.
Хорошо, так что я понял это:
- У меня есть два проекта; Ядро и Core.UnitTest. Core — это фактическая библиотека, а Core.UnitTest — проект модульного тестирования библиотеки 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 будет нормально работать при передаче методу в основной библиотеке. Общее свойство Range будет работать, тогда как отсутствующее свойство Index вызовет исключение MissingMethodException при доступе.
- Вышеупомянутое поведение работает даже с фиктивными типами. Смоделированный объект Mock[Excel.ListRow] будет нормально работать при пересечении границы сборки.
- К сожалению, поведение, описанное в предыдущем пункте, работает только при сборке сборок в Visual Studio 2012. Когда я создаю свои сборки в Visual Studio 2010 и отлаживаю свой код, я вижу, как фиктивный экземпляр ListRow передается в метод моего основного проекта. В тот момент, когда экземпляр пересекает границу сборки, все методы и свойства ListRow теряют свою реализацию и вызывают исключения MissingMethodException.
- Теперь самое интересное: мне действительно удалось смягчить эту проблему, убедившись, что оба встроенных типа ListRow выровнены. Например. чтобы компилятор создавал одно и то же представление ListRow в обоих проектах, я убедился, что в моем проекте UnitTest используются одни и те же методы и свойства. Это означает добавление фиктивных строк, таких как: var dummy = listRow.Index. Как только компилятор создал идентичные представления моего встроенного типа ListRow, экземпляру было разрешено пересекать границы сборки без потери своей реализации.
Тем не менее, остается вопрос: в чем причина такой разницы в поведении Visual Studio 2010 и Visual Studio 2012?
ОБНОВЛЕНИЕ: 11 сентября 2012 г.
Демонстрационное решение: http://temp-share.com/show/KdPf6066h< /а>
Я создал небольшое решение, чтобы продемонстрировать эффект. Решение состоит из библиотеки и проекта UnitTest. Оба ссылаются на Microsoft.Office.Interop.Excel.Range с включенным EIT. Тест отлично работает в VS2012, но выдает MissingMethodException в VS2010. Раскомментирование фиктивной строки в тесте заставит ее работать в VS2010.
ПОСЛЕДНЕЕ ОБНОВЛЕНИЕ: 29 декабря 2012 г.
Мои извинения за позднее обновление. Мой коллега нашел решение, однако я не смог воспроизвести его на своей машине. Тем временем наша компания перешла на TFS2012, поэтому для меня это больше не проблема блокировки. Мой коллега сделал два самых важных вывода:
- Семантика платформы «Любой ЦП» изменилась с Visual Studio 2010 на Visual Studio 2012. Это приведет к созданию разных .DLL в зависимости от того, используете ли вы VS2010 или VS2012.
- Оба проекта ссылались на разные версии Microsoft.Office.Interop.Excel.
Я проверил свои проекты и выправил ссылки, но это не имело значения. После этого я пробовал разные варианты платформ как в VS2010, так и в VS2012, но не смог добиться удовлетворительного результата. Я приму ответ Джереми, так как он был самым полезным. Спасибо всем за вашу помощь.
Microsoft.Office.Interop.Excel
? - person Claus Jørgensen   schedule 02.11.2012ListRow
, я вижу, что у него есть одно свойствоRange
с работающим геттером. Издевательский объект передается в метод, который я хочу протестировать. Когда я вхожу в этот метод (который находится в другой сборке), мой имитируемый объект внезапно имеет больше свойств. Однако в VS2012 свойствоRange
все еще работает. В VS2010 этого нет. Все дополнительные свойства генерируют MissingMethodExceptions, как и следовало ожидать. - person Martin Devillers   schedule 03.11.2012