如何使用Moq模拟Microsoft.Office.Interop.Excel.Range?

Lau*_*rpf 6 .net c# unit-testing moq mocking

我想模拟Microsoft.Office.Interop.Excel.Range(和其他Microsoft.Office.Interop.Excel接口)来单元测试我的应用程序.我在C#中使用Moq 4.0.10827和.NET 4.

在我的单元测试中,我尝试按如下方式设置模拟的行为:

        var range = new Mock<Microsoft.Office.Interop.Excel.Range>();
        range.Setup(r => r.get_Value(1)).Returns("Something");

        var classBeingTested = new MyClass(range.Object);
Run Code Online (Sandbox Code Playgroud)

在单元测试的代码中,我使用Range如下:

    public MyClass(Range range)
    {
        var value = range[1].ToString();
    }
Run Code Online (Sandbox Code Playgroud)

测试运行时会产生以下异常:

        Error: Missing method 'instance object [My.Example.Implementation.MyClass] Microsoft.Office.Interop.Excel.Range::get__Default(object,object)' from class 'Castle.Proxies.RangeProxy'.
Run Code Online (Sandbox Code Playgroud)

如何成功实现此模拟?我意识到将Excel Interop功能与/sf/answers/664035851/等模式隔离是一种潜在的解决方案; 但是,我更高兴能够从Microsoft.Office.Interop.Excel接口创建模拟.

编辑:有关此问题的更多详细信息

好的,这很奇怪.我已经创建了一个项目来测试jimmy_keen的建议.有用.但是,当我使用相同的建议来测试我遇到问题的项目时,会抛出以下异常:

Error: Missing method 'instance object [My.Example.Implementation.MyClass] Microsoft.Office.Interop.Excel.Range::get__Default(object,object)' from class 'Castle.Proxies.RangeProxy'.
Run Code Online (Sandbox Code Playgroud)

由于jimmy_keen的建议在其他项目上运行良好,我开始怀疑我正在测试代码的项目有问题.所以,我创建了一个测试解决方案,详细说明了这个问题:http://www7.zippyshare.com/v/70834394/file.html

问题的根源似乎是项目包含另一个类(未经过单元测试),基本上包含以下代码:

using Microsoft.Office.Interop.Excel;
namespace Project
{
    public class UnTestedClass
    {
        public UnTestedClass(Worksheet sheet)
        {
            var foo = sheet.Range["Description"].Column;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我不明白为什么会导致这个问题,因为我根本没有在单元测试中使用UnTestedClass.我错过了应该如何使用Moq,或者我偶然发现了一个错误?

k.m*_*k.m 5

您的代码访问索引器,这就是您需要模拟的内容:

var range = new Mock<Microsoft.Office.Interop.Excel.Range>();
range.Setup(r => r[1, It.IsAny<object>()]).Returns("something");
Run Code Online (Sandbox Code Playgroud)

请注意,Range索引器实际上需要两个参数 - 因此It.IsAny<object>()调用中的约束.

  • @LauriHarpf:这很有意思.显然,它是编译器生成代码的"问题".由*Project*中的编译器生成的`Range`类型接口具有额外属性(`Column`,即).我不知道这对Castle来说会有什么问题...但它是COM.例如,如果您使用ILSpy检查程序集,您将看到我的意思.编译器生成的代码不同(即使类是相同的),这一定是问题.注意,如果你存在`range.Setup(r => r.Column).Returns(0);`这个测试也将通过. (2认同)