Mocked object doesn't have all properties shown in Intellisense - in one project but has them in the other

夙愿已清 提交于 2019-12-30 11:49:13

问题


I'm mocking VSTO objects and in one project (I didn't write) it has this code:

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

The Intellisense ToolTip for the mockSheets shows 6 properties:

The line with the break point works in this project.

However I have the same code in a different project (same references, namespaces, etc.), yet the Intellisense ToolTip for the mockSheets only shows 1 property:

I know this is the root cause that I'm trying to solve, but fyi the actual problem is:

Cannot perform runtime binding on a null reference

EDIT:

The Sheet Object is mocked:

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);
}

回答1:


This is a wild guess, but Office Interop arrays are 1 based, not 0 based. I havent looked into it but this may be defined in the metadata. Try this:

for (int i = 0; i < numSheets; i++)
{
    listOfSheets.Add(Sheet);
    listOfSheets[i].Name = MockSheetName + (i + 1);
    `mockSheets[i + 1].Returns(listOfSheets[i]);`
}



回答2:


Some history:

I was getting a compile issue with these errors:

1.Predefined type 'Microsoft.CSharp.RuntimeBinder.Binder' is not defined or imported
2.One or more types required to compile a dynamic expression cannot be found. Are you missing references to Microsoft.CSharp.dll and System.Core.dll?

So I found this article and referenced the Microsoft.CSharp library: C# 4.0 and .Net 3.5

To the point: The class I've been showing essentially Mocks the Excel Object Model and I copied this class from one project to the other (I cant reference the other project as its actually separate project plus it would have caused circular dependency) I found the Returns extension method was listed in intellisense but I got a "Could not resolve Symbol" when compiling. Even though going to Definition was the same in both classes/projects. To get around this initially I did the commented out lines:

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;
    }
}

This point is a bit of a red-herring but removing the Microsoft.CSharp dll actually allowed the Returns extension method to resolve successfully. Then I found removing the Microsoft.CSharp dll resolved my problem, it all just worked, the mockSheet object has all its properties and was able to execute successfully without the "Cannot perform runtime binding on a null reference" error.

Oh and a tip for anyone Mocking Interop Types, be extra careful to set this:




回答3:


Sounds like the following may be the cause:

VSTO Specific Project to be tested (Addin/taskpane/etc)
VSTO ver: VSTO 3.0 SP1
.NET ver: .NET 3.5 SP1

VS 2010 Test project for project above
defaults to
.NET Ver: .NET 4.0

This would create a referencing problem when going to mock up the objects as the test project is expecting to be able to use MS.Csharp (i guess) and possibly other references.

So the exception is not really refering to the Null value returned by the mock object at all, but rather a null binding exception caused by not being able to load .NET 4.0's CSharp library.

Therefore as you discovered the solution is to remove .net 4.0 Csharp reference. It is perhaps unnecessary although to set the project to run under .net 3.5? Not sure you would have to test if any other problems occur. But I guess better to keep test projects on .net 4 if you can. Unless someone can indicate if this is not best practise.




回答4:


This is a reminder to myself everytime I write Nsubstitute Excel Unit Tests. I have battled with this error too many times.

You will get the error: Cannot perform runtime binding on a null reference

When you have referened the .Net Excel Object Library, you MUST reference the COM Microsoft Excel 14.0 Object Library. Once the COM interop Excel DLL is referenced, click F4 to see the DLLs Properties, remember to set the COM Interop NOT to Embed Interop Types.

.Excel Here is a working Project file:

<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>

The offender is this .Net Interop reference (needs to be the COM reference):

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


来源:https://stackoverflow.com/questions/9816243/mocked-object-doesnt-have-all-properties-shown-in-intellisense-in-one-project

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!