我有一个.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'.
此异常意味着我忘记在模拟上设置适当的属性getter。事实并非如此:
_listRowMock.Setup(m => m.Range).Returns(_rangeMock.Object);
现在我可以想象Moq对Interop Types的效果可能不太好。但我发现最令人费解的是,这些测试在Visual Studio 2012中运行良好,但在Visual Studio 2010中失败。
为什么我的Visual Studio会影响我的代码行为?
更新时间:2012年3月3日
好的,所以我明白了这一点:
问题仍然存在:导致Visual Studio 2010和Visual Studio 2012之间的行为差异的原因是什么?
更新时间:2012年9月11日
演示解决方案:http://temp-share.com/show/KdPf6066h
我已经创建了一个小解决方案来演示效果。该解决方案由一个库和一个UnitTest项目组成。两者都引用了Microsoft.Office.Interop.Excel.Range并启用了EIT。该测试在VS2012中正常工作,但在VS2010中抛出MissingMethodException。在测试中取消注释虚拟线将使其在VS2010中工作。
最终更新:2012年12月29日
我对最新的更新表示歉意。我的一位同事找到了解决方案,但是我无法在我的机器上重现它。与此同时,我们公司已经转向TFS2012,因此这不再是我的阻塞问题。我的同事做出的两个最重要的结论是:
我检查了我的项目并理顺了参考文献,但没有任何区别。之后,我在VS2010和VS2012中尝试了不同的平台变体,但无法产生令人满意的结果。我会接受杰里米的回答,因为这是最有帮助的。谢谢大家的帮助。
答案 0 :(得分:5)
编辑:当我在Visual Studio 2012中尝试并且目标.Net 4.0时,它适用于我,只使用.Net PIA而不是COM参考。相同的解决方案在VS2010中不起作用。
VS2010加载Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll's
的版本10.0.30319.1和VS2012加载版本11.0.50727.1。您可以在“模块”窗口中看到不同的版本。
我设法让它在VS2010中运行:
以下是我的解决方案http://temp-share.com/show/Pf3Ypip62,方便大家。它包含所有Moq参考。我有Excel 2007(即第12版) - 所以请调整对Office 14的引用。
包含待测方法的项目必须通过.Net参考选项卡使用PIA Microsoft.Office.Interop.Excel
。
在单元测试项目中,您必须通过COM参考选项卡使用Microsoft Excel 1X.0 Object Library
- 它是一个ActiveX。
令人困惑的是,在解决方案资源管理器中,它们都被调用:Microsoft.Office.Interop.Excel
还有一个警告,我不知道如何解决方法 - 你必须使用.Net 3.5框架我实际上希望微软在2012年修复它,因为我无法工作如何与.Net 4.0中的所有项目一起完成。针对.Net 3.5&amp ;;的混合项目的一些解决方案4.0还可以。
我遇到了很多麻烦,请点击此处How do I avoid using dynamic when mocking an Excel.worksheet?并看到我问过的这个问题:Mocked object doesn't have all properties shown in Intellisense - in one project but has them in the other。
无论如何,这是如何让它在VS 2010中运行。我很高兴它在2012年得到解决!
答案 1 :(得分:3)
我试图重现这一点,对我来说,即使在VS 2012中它也不起作用。
使用“嵌入互操作类型”编译项目时,C#编译器会生成一个只有您正在访问的成员的内部类型,并且实现似乎实际上似乎使用IDispatch通过id调用COM对象的方法。
从您的描述中我了解到,您在VS 2012中的测试项目不会访问属性(甚至不是为了模拟它们),但测试仍然成功并且测试项目中生成的类型 拥有这些成员。
如果您确实遇到了这种情况,请查看测试内容.dll并查看互操作类型是如何生成的?您可以使用ildasm.exe
等工具。
如果测试.dll中的互操作类型包含所有成员,即使是那些在测试中不访问的成员,这可能会给出一个线索,即差异与VS 2012中生成互操作类型的方式有关。
另外,如果您可以附加一个小的最小VS 2012解决方案来重现问题,那么它可能对诊断它有很大帮助。
答案 2 :(得分:0)
首先检查在VS2010中向项目添加库时,确保创建了模拟对象,如
Mock<DocumentService> _mock = new Mock<DocumentService>();
.NET 4.0允许将主互操作程序集嵌入到程序集中,这样就不需要将它们与应用程序一起部署。在VS2010中打开程序集中的属性选项卡并检查嵌入式互操作类型.mkae确定它的真。
要实例化excel,Excel.Application xlapp = new Excel.Application();
希望它能起作用..
答案 3 :(得分:0)
我发现,至少在VS2015中,我仍然可以在我的测试组件中嵌入互操作类型,但在我的测试项目中将PIA程序集引用上的“Embed”设置为false,我没有重复这个。