【问题标题】:Partial mock of a class with private constructor具有私有构造函数的类的部分模拟
【发布时间】:2011-11-13 18:12:51
【问题描述】:

我正在尝试使用 Moq 在一个看起来像这样的类上编写一些单元测试:

Public Interface IAwesomeInterface
    Function GetThis() As Integer
    Function GetThisAndThat(ByVal that As Integer) As Integer
End Interface


Public Class MyAwesomeClass
    Implements IAwesomeInterface

    Dim _this As Integer

    ''' <summary>
    ''' injection constructor
    ''' </summary>
    Private Sub New(ByVal this As Integer)
        Me._this = this
    End Sub

    ''' <summary>
    ''' default factory method
    ''' </summary>
    Public Shared Function Create() As IAwesomeInterface
        Return New MyAwesomeClass(42)
    End Function

    Public Overridable Function GetThis() As Integer Implements IAwesomeInterface.GetThis
        Return _this
    End Function

    Public Function GetThisAndThat(ByVal that As Integer) As Integer Implements IAwesomeInterface.GetThisAndThat
        Return GetThis() + that
    End Function
End Class
  • 参数化构造函数是私有的或内部的
  • 两种方法之一依赖于另一种方法的结果

我想检查当GetThisOrThat 被调用时,它实际上调用了GetThis。但我也想模拟 GetThis 以便它返回一个特定的众所周知的值。

对我来说,这是一个 Partial Mocking 的例子,我们基于一个类创建一个 Mock,并为构造函数传递参数。这里的问题是没有公共构造函数,因此,Moq 不能调用它...... 我尝试使用 Visual Studio 为 MSTest 生成的访问器,并使用这些访问器进行模拟,这就是我想出的:

<TestMethod()>
Public Sub GetThisAndThat_calls_GetThis()
    'Arrange
    Dim dummyAwesome = New Mock(Of MyAwesomeClass_Accessor)(56)
    dummyAwesome.CallBase = True

    dummyAwesome.Setup(Function(c) c.GetThis()).Returns(99)

    'Act
    Dim thisAndThat = dummyAwesome.Object.GetThisAndThat(1)

    'Assert
    Assert.AreEqual(100, thisAndThat)' Expected:<100>. Actual:<57>. 

    dummyAwesome.Verify(Function(d) d.GetThis, Times.Once, "GetThisAndThat should call GetThis")

End Sub

...但这失败了。执行测试时,GetThis 返回 56 而不是 99。

我做错了什么吗? 在我阅读的其他问题中,我没有看到提到这种情况。

更新:基于 Tim Long 的回答

我将此添加到我正在测试的程序集的 AssemblyInfo.vb 中:

<Assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")> 

(不包括 PublicKey,即不像文档中指定的那样:http://code.google.com/p/moq/wiki/QuickStart in Advanced Features

并制作了构造函数Friend (=internal) 而不是Private。 我现在可以直接使用 internal 构造函数,而不是使用 MSTests Accessors :

<TestClass()>
Public Class MyAwesomeTest

    <TestMethod()>
    Public Sub GetThisAndThat_calls_GetThis()
        'Arrange
        Dim dummyAwesome = New Mock(Of MyAwesomeClass)(56)
        dummyAwesome.CallBase = True

        dummyAwesome.Setup(Function(c) c.GetThis()).Returns(99)

        'Act
        Dim thisAndThat = dummyAwesome.Object.GetThisAndThat(1)

        'Assert
        Assert.AreEqual(100, thisAndThat)

        dummyAwesome.Verify(Function(d) d.GetThis, Times.Once, "GetThisAndThat should call GetThis")

    End Sub

End Class

【问题讨论】:

    标签: .net vb.net unit-testing moq mstest


    【解决方案1】:

    您可以将您的构造函数设为内部而不是私有,然后使用InternalsVisibleTo 属性将您的单元测试指定为“朋友程序集”。

    或者,可能值得关注Moles isolation framework(MS 研究)

    【讨论】:

    • 我尝试将构造函数标记为internal(即Friend)并根据Moq的文档设置InternalsVisibleTo(即DynamicProxyGenAssembly2和PublicKey),但它失败并出现错误System.NotSupportedException: Parent does not have a default constructor. The default constructor must be explicitly defined. .不过,不包括您所说的 PublicKey 工作......所以谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多