我有一个班,负责构建用于导出的PPT幻灯片。为了进行单元测试,我创建了一个接口,因此可以使用Moq进行模拟;到目前为止一切都很棒但是在尝试测试我的方法被调用时遇到了困难。这是一种无效方法,所以此时我只想知道该方法已被命中。
这是我的界面:
interface IPowerpointExporter
{
void AddSlides(int amount);
void setTitle(string title);
}
这是我的单元测试:
[TestMethod]
public void testPPTObject()
{
var mockPPT = new Mock<IPowerpointExporter>();
mockPPT.Setup(m => m.AddSlides(1)).Verifiable();
mockPPT.Object.AddSlides(1);
mockPPT.VerifyAll();
}
然而,当我来电话AddSlides()
时,我得到GeneratorException
。对此的解释是我的IPowerpointExporter无法访问。我有一种感觉,这是因为我试图在界面上调用一个方法,虽然我不确定,因为此时我已经在mockPPT.Object.AddSlides();
得到了我的对象。
请注意,我还尝试了以下尝试使用实际对象而不是Interface.Object。这也给出了同样的例外:
[TestMethod]
public void testPPTObject()
{
var mockPPT = new Mock<IPowerpointExporter>();
mockPPT.Setup(m => m.AddSlides(1)).Verifiable();
ExportPowerPoint temp = (ExportPowerPoint)mockPPT.Object;
temp.AddSlides(1);
mockPPT.VerifyAll();
}
使用Moq如何检查我的方法是否被调用?我在上面沿着正确的方向做了什么?
答案 0 :(得分:4)
您可能会遇到该异常,因为您的界面不是public
,或者对Moq程序集可见。请参阅this question以解决此问题。
如果这只是帮助您学习Moq的虚拟代码,那么请继续阅读。
但是,如果这是您认为有价值的实际测试,那么您还有其他更基本的问题。在您的第一个示例中,您完全没有做任何测试代码的事情!让我们逐行完成它:
var mockPPT = new Mock<IPowerpointExporter>();
您创建了IPowerpointExporter
界面的模拟,到目前为止一直很好。
mockPPT.Setup(m => m.AddSlides(1)).Verifiable();
你告诉模拟人员期望调用它的AddSlide
方法,参数为1
,并且可以验证该方法。到目前为止没问题。
mockPPT.Object.AddSlides(1);
但是现在它已经脱轨了。您只是在模拟上调用该方法,就像您刚刚设置的那个。 Object
属性是虚拟对象,它只能执行设置操作,与实际实现无关!
mockPPT.VerifyAll();
现在您确认已调用所有可验证的方法。你在这个测试中所做的只是验证了Moq的工作原理;你的代码从未被触及。
现在让我们看看你的第二个例子中改变的代码:
ExportPowerPoint temp = (ExportPowerPoint)mockPPT.Object;
temp.AddSlides(1);
该演员表永远无法工作。 Object
属性只是一些代理(实际上是一种动态类型),由Moq生成,对于它正在嘲笑的界面的任何具体实现一无所知
答案 1 :(得分:1)
发生此异常是因为Moq无法访问IPowerpointExporter
接口。
您可以制作IPowerpointExporter
界面public
,并完美测试:
public interface IPowerpointExporter
{
void AddSlides(int amount);
void setTitle(string title);
}
....
[TestMethod]
public void testPPTObject()
{
var mockPPT = new Mock<IPowerpointExporter>();
mockPPT.Setup(m => m.AddSlides(1)).Verifiable();
ExportPowerPoint temp = (ExportPowerPoint)mockPPT.Object;
temp.AddSlides(1);
mockPPT.VerifyAll();
}
但是,当您需要对非公共类型进行测试时,可以在程序集中使用InternalsVisibleTo
属性使Moq可以看到类型。
[assembly:InternalsVisibleTo("DynamicProxyGenAssembly2")]