使用私有构造函数的类的部分模拟

时间:2011-09-09 12:15:30

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

我正在尝试使用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
  • 参数化构造函数是private或internal
  • 这两种方法中的一种依赖于另一种
  • 的结果

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

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

<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

并使构造函数Friend(= internal)代替Private。 我现在可以直接使用internal构造函数,而不是使用MSTests Accessor

<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

1 个答案:

答案 0 :(得分:2)

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

或者,值得一看Moles isolation framework(MS Research)