Смоделированный объект не имеет всех свойств, показанных в Intellisense - в одном проекте, но имеет их в другом

Я издеваюсь над объектами VSTO, и в одном проекте (я не писал) у него есть этот код:

var listOfSheets = new List<Worksheet>();
var mockSheets = Substitute.For<Sheets>();
mockSheets.Count.Returns(listOfSheets.Count);

Подсказка Intellisense для mockSheets показывает 6 свойств:

NSubstitute All Properties

Строка с точкой останова работает в этом проекте.

Однако у меня есть тот же код в другом проекте (те же ссылки, пространства имен и т. д.), но подсказка Intellisense для mockSheets показывает только 1 свойство:

NSubstitute Only one Property

Я знаю, что это основная причина, которую я пытаюсь решить, но на самом деле проблема такова:

Не удается выполнить привязку среды выполнения к нулевой ссылке

Невозможно выполнить привязку во время выполнения к нулевой ссылке

РЕДАКТИРОВАТЬ:

Объект листа высмеивается:

public static Worksheet Sheet
{
    get
    {
        var mockSheet = Substitute.For<Worksheet>();
        mockSheet.Name = MockSheetName;
        mockSheet.Visible = XlSheetVisibility.xlSheetVisible;

        return mockSheet;
    }
}

public static Workbook Workbook()
{
    return Workbook(1);
}

person Jeremy Thompson    schedule 22.03.2012    source источник
comment
Если вы вручную издеваетесь над Sheets (создаете класс FakeSheets, производный от Sheets), работает ли он так, как ожидалось?   -  person David Tchepak    schedule 23.03.2012
comment
@DavidTchepak Привет, Дэвид, спасибо, что поддержал меня в этом вопросе, да, Sheets уже высмеяли. Пожалуйста, смотрите мое редактирование. Я думаю, что есть основная причина, по которой свойства не отображаются, знаете ли вы какие-либо методы отладки, чтобы раскрыть это? На самом деле я скачаю исходный код NSubstitute и буду использовать его, а не выпускать DLL.   -  person Jeremy Thompson    schedule 23.03.2012
comment
@DavidTchepak У меня нет прав администратора (на работе), и я не могу установить NuGet :( У меня даже нет рефлектора, поэтому я даже не могу декомпилировать dll :( Знаете ли вы какой-либо другой способ получить исходный код?   -  person Jeremy Thompson    schedule 23.03.2012
comment
Я имел в виду, если вы создаете подделки вручную (т.е. без использования NSubstitute), работает ли это так, как ожидалось? Если вам нужен исходный код, вы можете взять его с github.com/nsubstitute/NSubstitute/downloads ( можете скачать без проверки) или попробуйте ilspy декомпилировать (почти уверен, что ему не нужен администратор).   -  person David Tchepak    schedule 23.03.2012


Ответы (4)


Это дикое предположение, но массивы Office Interop основаны на 1, а не на 0. Я не изучал это, но это может быть определено в метаданных. Попробуй это:

for (int i = 0; i < numSheets; i++)
{
    listOfSheets.Add(Sheet);
    listOfSheets[i].Name = MockSheetName + (i + 1);
    `mockSheets[i + 1].Returns(listOfSheets[i]);`
}
person Jake Ginnivan    schedule 22.03.2012
comment
+1 спасибо Джейк. Это не было исправлением, но любой совет, который вы можете дать, очень ценится. Пожалуйста, смотрите редактирование, мой Print Screen сегодня работает :) - person Jeremy Thompson; 23.03.2012

Немного истории:

У меня возникла проблема с компиляцией с этими ошибками:

1. Предопределенный тип «Microsoft.CSharp.RuntimeBinder.Binder» не определен или не импортирован
2. Не удается найти один или несколько типов, необходимых для компиляции динамического выражения. Вам не хватает ссылок на Microsoft.CSharp.dll и System.Core.dll?

Поэтому я нашел эту статью и сослался на библиотеку Microsoft.CSharp: >C# 4.0 и .Net 3.5

К сути: Класс, который я показывал, по сути имитирует объектную модель Excel, и я скопировал этот класс из одного проекта в другой (я не могу ссылаться на другой проект как на отдельный проект плюс это вызвало бы циклическую зависимость) Я обнаружил, что метод расширения Returns был указан в intellisense, но при компиляции я получил «Не удалось разрешить символ». Несмотря на то, что переход к определению был одинаковым в обоих классах/проектах. Чтобы обойти это, я сначала сделал закомментированные строки:

public static Range Cell
{
    get
    {
        var mockCell = Substitute.For<Range>();
        mockCell.Address.Returns("$A$1");
        mockCell.Formula = "=1+1";
        mockCell.ToString().Returns(mockCell.Formula.ToString());
        //mockCell.ToString().Returns(info => mockCell.Formula.ToString());
        //SubstituteExtensions.Returns(mockCell.ToString(),  mockCell.Formula.ToString());
        mockCell.Worksheet.Returns(Sheet);
        mockCell.Worksheet.Name.Returns(MockSheetName);

        return mockCell;
    }
}

Этот момент немного отвлекающий маневр, но удаление DLL Microsoft.CSharp фактически позволило успешно разрешить метод расширения Returns. Затем я обнаружил, что удаление dll Microsoft.CSharp решило мою проблему, все это просто сработало, объект mockSheet имеет все свои свойства и может успешно выполняться без «Невозможно выполнить привязку среды выполнения к нулевой ссылке». ошибка.

О, и совет для тех, кто имитирует типы взаимодействия, будьте особенно осторожны, чтобы установить это:

введите здесь описание изображения

person Jeremy Thompson    schedule 23.03.2012
comment
Этот ответ потрясающий, вау, ты хардкорный кодер, чувак. Любые дополнительные подсказки о том, как вы это определили? - person Anonymous Type; 23.03.2012
comment
нет, это все ты... Я просто бросал (С) острые предметы тебе в голову, пока ты не понял - person Anonymous Type; 23.03.2012

Похоже, причиной может быть следующее:

Конкретный тестируемый проект VSTO (надстройка, панель задач и т. д.)
Версия VSTO: VSTO 3.0 SP1
Версия .NET: .NET 3.5 SP1

Тестовый проект VS 2010 для вышеуказанного проекта
по умолчанию
.NET Ver: .NET 4.0

Это создаст проблему со ссылками при создании макета объектов, поскольку ожидается, что тестовый проект сможет использовать MS.Csharp (я полагаю) и, возможно, другие ссылки.

Таким образом, исключение на самом деле не относится к значению Null, возвращаемому фиктивным объектом, а скорее к нулевому исключению привязки, вызванному невозможностью загрузить библиотеку CSharp .NET 4.0.

Поэтому, как вы обнаружили, решение состоит в том, чтобы удалить ссылку .net 4.0 Csharp. Возможно, нет необходимости настраивать проект для работы под .net 3.5? Не уверен, что вам придется проверять, возникают ли какие-либо другие проблемы. Но я думаю, что лучше оставить тестовые проекты на .net 4, если это возможно. Если кто-то не может указать, не является ли это лучшей практикой.

person Anonymous Type    schedule 23.03.2012
comment
также хороший момент о том, чтобы не встраивать типы (особенность .net 4) - person Anonymous Type; 23.03.2012

Это напоминание мне каждый раз, когда я пишу модульные тесты Nsubstitute Excel. Я слишком много раз сталкивался с этой ошибкой.

Вы получите сообщение об ошибке: Невозможно выполнить привязку во время выполнения к нулевой ссылке.

Когда вы ссылаетесь на библиотеку объектов .Net Excel, вы ДОЛЖНЫ ссылаться на библиотеку объектов COM Microsoft Excel 14.0. После ссылки на COM-взаимодействие Excel DLL нажмите F4, чтобы увидеть свойства DLL, не забудьте установить для COM-взаимодействия НЕ значение Embed Interop Types.

.Excel Вот рабочий файл проекта:

<ItemGroup>
    <Reference Include="Microsoft.Office.Interop.Excel.Extensions">
      <HintPath>..\..\Refs\Microsoft.Office.Interop.Excel.Extensions.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
    <Reference Include="NSubstitute">
      <HintPath>..\..\Refs\NSubstitute.dll</HintPath>
    </Reference>
    <Reference Include="System" />
    <Reference Include="System.Core">
      <RequiredTargetFramework>3.5</RequiredTargetFramework>
    </Reference>
    <Reference Include="System.Data" />
    <Reference Include="System.Data.DataSetExtensions" />
    <Reference Include="System.Runtime.Serialization" />
    <Reference Include="System.Xml" />
    <Reference Include="System.Xml.Linq" />
    <Reference Include="UIAutomationProvider" />
    <Reference Include="VSTOContrib.Core, Version=0.9.0.52, Culture=neutral, processorArchitecture=MSIL" />
    <Reference Include="WindowsBase" />
    <Reference Include="WindowsFormsIntegration" />
  </ItemGroup>
  <ItemGroup>
    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
      <Visible>False</Visible>
    </CodeAnalysisDependentAssemblyPaths>
  </ItemGroup>
  <ItemGroup>
    <Compile Include="MockFactory.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
    <Compile Include="UnitTests.cs" />
  </ItemGroup>
  <ItemGroup>
      <COMReference Include="Microsoft.Office.Core">
      <Guid>{2DF8D04C-5BFA-101B-BDE5-00AA0044DE52}</Guid>
      <VersionMajor>2</VersionMajor>
      <VersionMinor>4</VersionMinor>
      <Lcid>0</Lcid>
      <WrapperTool>primary</WrapperTool>
      <Isolated>False</Isolated>
    </COMReference>
    <COMReference Include="Microsoft.Office.Interop.Excel">
      <Guid>{00020813-0000-0000-C000-000000000046}</Guid>
      <VersionMajor>1</VersionMajor>
      <VersionMinor>6</VersionMinor>
      <Lcid>0</Lcid>
      <WrapperTool>primary</WrapperTool>
      <Isolated>False</Isolated>
    </COMReference>
  </ItemGroup>

Нарушителем является эта ссылка .Net Interop (должна быть ссылка COM):

<Reference Include="Microsoft.Office.Interop.Excel, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c, processorArchitecture=MSIL">
  <EmbedInteropTypes>True</EmbedInteropTypes>
</Reference>
person Jeremy Thompson    schedule 21.08.2012