Частичная имитация класса с приватным конструктором - PullRequest
1 голос
/ 09 сентября 2011

Я пытаюсь написать несколько модульных тестов для класса, который выглядит следующим образом, используя 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, чтобы он возвращал определенное общеизвестное значение.

Для меня это пример частичного пересмешивания, где мы создаем пересмешку на основе класса, передавая параметры дляконструкторПроблема здесь в том, что нет открытого конструктора, и поэтому Moq не может его вызвать ... Я попытался использовать Accessors, сгенерированные 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.

Я что-то не так делаю?В других вопросах, которые я читал, я не видел упоминания об этом сценарии.

ОБНОВЛЕНИЕ: основано на ответе Тима Лонга

Я добавил это кAssemblyInfo.vb сборки, которую я тестирую:

<Assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")> 

(без учета PublicKey, т.е. не так, как указано в документации: http://code.google.com/p/moq/wiki/QuickStart в Расширенные функции )

И сделал конструктор Friend (= internal) вместо Private.Теперь я могу напрямую использовать конструктор internal вместо MSTests Accessor s:

<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 Ответ

2 голосов
/ 12 сентября 2011

Вы можете сделать ваш конструктор Internal вместо private, а затем использовать атрибут InternalsVisibleTo, чтобы обозначить ваши юнит-тесты как «сборку друга».

Или, возможно, стоит взглянуть на Среду изоляции молей (MS Research)

...