Moq 和构造函数 - 测试初始化​​行为

Posted

技术标签:

【中文标题】Moq 和构造函数 - 测试初始化​​行为【英文标题】:Moq and constructors - testing initialisation behaviour 【发布时间】:2010-09-08 12:36:28 【问题描述】:

我希望能够使用 Moq 正确地测试一个类的初始化:

class ClassToTest

    public ClassToTest()
    
        Method1(@"C:\myfile.dat")
    

    public virtual void Method1(string filename)
    
        // mock this method
        File.Create(filename);
    

我想我可以使用CallBase 属性创建类的可测试版本,然后使用.Setup() 确保Method1() 不执行任何代码。

但是,创建Mock<ClassToTest>() 不会调用构造函数,如果调用了,那么执行Setup() 为时已晚!

如果这是不可能的,那么在确保构造函数正确运行的同时解决问题的最佳方法是什么?

编辑:为了更清楚,我向Method1() 添加了一个参数来获取文件名并添加了一些行为。我想编写的测试将是以下的工作版本:

[Test]
public void ClassToTest_ShouldCreateFileOnInitialisation()

    Mock<ClassToTest> mockClass = new Mock<ClassToTest>()  CallBase = true ;
    mockClass.Setup(x => x.Method1(It.IsAny<string>());

    mockClass.Verify(x => x.Method1(@"C:\myfile.dat"));

【问题讨论】:

在你走这条路之前,请先看看你的设计实践。不建议在构造函数中调用虚方法,因为它可能会导致难以跟踪的非常微妙的错误。详情请见***.com/questions/448258/…。 Method1() 在做什么需要模拟? 尽可能不要在构造函数中调用虚方法。如果你不能,你能粘贴你的测试吗? 我只声明方法 virtual 以便以后模拟它。如果这是错误的,那么我将不得不使用另一种方法......我添加了一个示例,这可能有助于澄清我正在尝试做的事情。 【参考方案1】:

Moq.Mock 内部(实际上在Moq 使用的CastleProxyFactory 内部)

mockClass.Object

会以Activator.CreateInstance()的方式调用构造函数

所以你的测试看起来像

[Test]
public void ClassToTest_ShouldCreateFileOnInitialisation()

    Mock<ClassToTest> mockClass = new Mock<ClassToTest>();
    mockClass.Setup(x => x.Method1(It.IsAny<string>());

    var o = mockClass.Object;

    mockClass.Verify(x => x.Method1(@"C:\myfile.dat"));

【讨论】:

以上是关于Moq 和构造函数 - 测试初始化​​行为的主要内容,如果未能解决你的问题,请参考以下文章

JAVA构造函数

复制构造函数的运用

使用 Moq 模拟 NHibernate ISession

面向对象:有关类和构造函数的基础知识

39.C#--面对对象构造函数及构造函数继承使用

构造函数与普通函数的区别