我想模拟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) 我正在开发人员使用不同IDE的环境中工作 - Eclipse,Netbeans和IntelliJ.我正在使用@Nonnull注释(javax.annotation.Nonnull)来指示方法永远不会返回null:
@Nonnull
public List<Bar> getBars() {
return bars; // this.bars is a final, initialized list
}
Run Code Online (Sandbox Code Playgroud)
如果他们执行以下操作之一,我希望其他开发人员收到警告:
IntelliJ支持第一种方案.第二个不是; 客户端不会被警告不需要检查null.
我们无论如何都计划转向收集集合的克隆而不是集合本身,所以最好忘记@Nonnull而是这样做:
public List<Bar> getBars() {
return new ArrayList<Bar>(bars);
}
Run Code Online (Sandbox Code Playgroud)
编辑:
为了澄清,我不打算为此更改IDE.我想知道上面提到的IDE是否支持我上面描述的内容 - 或者,如果有充分理由说明为什么它不受支持.
我明白了不要太依赖合同.但是,如果我用最后一段中的样式编写getBars()(返回列表的克隆),那么例如IntelliJ会标记任何代码的警告
if (foo.getBars() == null) { ... }
Run Code Online (Sandbox Code Playgroud)
如果您选择遵循此警告并删除空检查,则您似乎同样依赖于不更改的getBars()实现.但是,在这种情况下,您似乎依赖于实现细节而不是显式合同(与@Nonnull的情况一样).
编辑#2:
我不关心执行速度,空检查确实非常快.我担心代码可读性.考虑以下:
选项A:
if ((foo.getBars() == null || foo.getBars().size() < MAXIMUM_BARS) &&
(baz.getFoos() == null || baz.getFoos().size() < MAXIMUM_FOOS)) {
// do something
}
Run Code Online (Sandbox Code Playgroud)
选项B:
if (foo.getBars().size() < MAXIMUM_BARS &&
baz.getFoos().size() < MAXIMUM_FOOS) { …Run Code Online (Sandbox Code Playgroud)