[英]Moq & Interop Types: works in VS2012, fails in VS2010?
I have a .NET library project with about 500 unit tests. 我有一个.NET库项目,大约有500个单元测试。 All these tests run fine in Visual Studio 2012. However, some of my tests fail in Visual Studio 2010. In these failing tests, I use Moq to mock several Interop Types from Microsoft.Office.Interop.Excel
. 所有这些测试在Visual Studio 2012中运行良好。但是,我的一些测试在Visual Studio 2010中失败。在这些失败的测试中,我使用Moq从Microsoft.Office.Interop.Excel
模拟几个Interop类型。 The test fails immediately when attempting to access these mocked interop types: 尝试访问这些模拟的互操作类型时,测试立即失败:
Error: Missing method 'instance class Microsoft.Office.Interop.Excel.Range [ExcelAddIn.Core] Microsoft.Office.Interop.Excel.ListRow::get_Range()' from class 'Castle.Proxies.ListRowProxy'.
This exception implies that I forgot to setup the appropriate property getter on my mock. 这个异常意味着我忘了在mock上设置适当的属性getter。 Which is not the case: 事实并非如此:
_listRowMock.Setup(m => m.Range).Returns(_rangeMock.Object);
Now I can imagine that Moq might not work too well with Interop Types. 现在我可以想象Moq对于Interop类型可能效果不佳。 But what I find most puzzling is that these tests run fine in Visual Studio 2012, but fail in Visual Studio 2010. 但我发现最令人费解的是,这些测试在Visual Studio 2012中运行良好,但在Visual Studio 2010中失败。
Why is my Visual Studio influencing the behavior of my code? 为什么我的Visual Studio会影响我的代码行为?
UPDATE: 3-11-2012 更新:2012年3月11日
Ok, so I got it down to this: 好的,所以我明白了:
The question still remains though: What causes this difference in behavior between Visual Studio 2010 and Visual Studio 2012? 问题仍然存在:是什么导致Visual Studio 2010和Visual Studio 2012之间的行为差异?
UPDATE: 9-11-2012 更新:2012年9月11日
Demo Solution : http://temp-share.com/show/KdPf6066h 演示解决方案 : http : //temp-share.com/show/KdPf6066h
I have created a small solution to demonstrate the effect. 我已经创建了一个小解决方案来演示效果。 The solution consists of a library and a UnitTest project. 该解决方案由一个库和一个UnitTest项目组成。 Both reference Microsoft.Office.Interop.Excel.Range with EIT enabled. 两者都引用了Microsoft.Office.Interop.Excel.Range并启用了EIT。 The test works fine in VS2012 but throws MissingMethodException in VS2010. 该测试在VS2012中正常工作,但在VS2010中抛出MissingMethodException。 Uncommenting the dummy line in the test will make it work in VS2010. 在测试中取消注释虚拟线将使其在VS2010中工作。
FINAL UPDATE: 29-12-2012 最终更新:2012年12月29日
My apologies for the late update. 我为最新的更新道歉。 A colleague of mine found a solution, however I was unable to reproduce it on my machine. 我的一位同事找到了解决方案,但是我无法在我的机器上重现它。 In the meantime our company has made the switch to TFS2012 so this is no longer a blocking issue for me. 与此同时,我们公司已经转向TFS2012,因此这不再是我的阻塞问题。 The two most important conclusions my colleague made were: 我的同事做出的两个最重要的结论是:
I checked my projects and straightened out the references, but it made no difference. 我检查了我的项目并理顺了参考文献,但没有任何区别。 After that, I tried different variations of platforms in both VS2010 and VS2012 but was unable to produce a satisfactory result. 之后,我在VS2010和VS2012中尝试了不同的平台变体,但无法产生令人满意的结果。 I will accept Jeremy's answer as it was the most helpful. 我会接受杰里米的回答,因为这是最有帮助的。 Thank you all for your assistance. 谢谢大家的帮助。
Edit : It works for me when I try it in Visual Studio 2012 and target .Net 4.0, only using the .Net PIA's not the COM ref. 编辑:当我在Visual Studio 2012中尝试并且目标.Net 4.0时,它适用于我,仅使用.Net PIA而不是COM参考。 Same solution doesn't work in VS2010. 相同的解决方案在VS2010中不起作用。
VS2010 loads version's 10.0.30319.1 of the Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll's
and VS2012 loads version's 11.0.50727.1. VS2010加载版本10.0.30319.1的Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll's
和VS2012加载版本11.0.50727.1。 You can see the different version's in the Modules window. 您可以在“模块”窗口中看到不同的版本。
I managed to get it working in VS2010: 我设法让它在VS2010中运行:
Here is my solution http://temp-share.com/show/Pf3Ypip62 for everyone's convenience. 这是我的解决方案http://temp-share.com/show/Pf3Ypip62 ,方便大家。 It has all the Moq references included. 它包含所有Moq参考。 I have Excel 2007 (ie v12) - so please adjust references to Office 14. 我有Excel 2007(即v12) - 所以请调整对Office 14的引用。
The Project with methods to be Tested has to use the PIA Microsoft.Office.Interop.Excel
via the .Net reference tab. 具有待测试方法的项目必须通过.Net参考选项卡使用PIA Microsoft.Office.Interop.Excel
。
In the Unit Test Project you have to use the Microsoft Excel 1X.0 Object Library
via the COM reference tab - its an ActiveX. 在单元测试项目中,您必须通过COM参考选项卡使用Microsoft Excel 1X.0 Object Library
- 它是一个ActiveX。
The confusing thing is in Solution Explorer they are both called: Microsoft.Office.Interop.Excel 令人困惑的是,在解决方案资源管理器中,它们都被称为:Microsoft.Office.Interop.Excel
There is one other caveat that I dont know how to workaround - you have to use the .Net 3.5 framework and I was actually hoping Microsoft fixed it in 2012 as you found because I cant work how to do it with ALL projects in .Net 4.0. 还有一个警告,我不知道如何解决方法 - 你必须使用.Net 3.5框架,我实际上希望微软在2012年修复它,因为我找不到 .Net 4.0中的所有项目如何做到这一点。 Some solutions with mixed projects targeting .Net 3.5 & 4.0 are ok. 针对.Net 3.5和4.0的混合项目的一些解决方案是可以的。
I've had a lot of trouble with this, see here How do I avoid using dynamic when mocking an Excel.worksheet? 我遇到了很多麻烦,请参阅此处如何在模拟Excel.worksheet时避免使用动态? and also see this question I asked: Mocked object doesn't have all properties shown in Intellisense - in one project but has them in the other . 并且我也问过这个问题: 模拟对象没有Intellisense中显示的所有属性 - 在一个项目中但在另一个项目中有它们 。
Anyway this is how to get it working in VS 2010. I'm glad its resolved in 2012! 无论如何,这是如何让它在VS 2010中运行。我很高兴它在2012年得到解决!
I tried to reproduce this, and for me it doesn't work even in VS 2012. 我试图重现这一点,对我而言,即使在VS 2012中它也不起作用。
When you compile a project using "Embed Interop Types", the C# compiler generates an internal type that has only the members you are accessing, and the implementation actually seems to use IDispatch to call the method of the COM object by id. 使用“嵌入互操作类型”编译项目时,C#编译器会生成一个只包含您正在访问的成员的内部类型,实现似乎实际上似乎使用IDispatch通过id调用COM对象的方法。
From your description I understand that your test project in VS 2012 does not access the properties (not even in order to mock them), but the test still succeeds and the generated type in the test project does have these members. 从您的描述中我了解到您在VS 2012 中的测试项目不访问属性(甚至不是为了模拟它们),但测试仍然成功,测试项目中生成的类型确实具有这些成员。
If this is indeed what you are experiencing, can you please look at the content of your test .dll and see how the interop type was generated? 如果您确实遇到了这种情况,请查看测试内容.dll并查看互操作类型是如何生成的? You can use a tool such as ildasm.exe
. 您可以使用ildasm.exe
等工具。
If the interop type in the test .dll contains all the members, even those you don't access in the test, this may give a clue that the difference is related to the way the interop types are generated in VS 2012. 如果测试.dll中的互操作类型包含所有成员,即使您在测试中未访问的成员,这可能会给出一个线索,即差异与VS 2012中生成互操作类型的方式有关。
Also, if you can attach a small minimal VS 2012 solution which reproduces the problem, it may greatly help in diagnosing this. 此外,如果您可以附加一个小的最小VS 2012解决方案来重现问题,它可能会有助于诊断这一点。
First of all check while adding library to the project in VS2010, make sure you created the mock object like 首先在VS2010中向库中添加库时进行检查,确保创建了模拟对象
Mock<DocumentService> _mock = new Mock<DocumentService>();
Also .NET 4.0 allows primary interop assemblies to be embedded into your assembly so that you don't need to deploy them alongside your application.Open the properties tab in the assembly in VS2010 and check the Embed Interop types.mkae sure its true. 此外,.NET 4.0允许将主互操作程序集嵌入到程序集中,这样您就不需要将它们与应用程序一起部署。在VS2010中打开程序集中的属性选项卡并检查嵌入式互操作类型.mkae确定它是真的。
And to instantiate excel, Excel.Application xlapp = new Excel.Application();
并实例化excel, Excel.Application xlapp = new Excel.Application();
Hope it will work.. 希望它能起作用..
我发现,至少在VS2015中,我仍然可以在我测试的程序集中嵌入interop类型,但是在我的测试项目中将PIA程序集引用上的“Embed”设置为false,我没有重复这个。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.