使用Rhino.Mocks正确分配了模拟对象的断言属性

时间:2011-09-28 04:15:29

标签: unit-testing nunit rhino-mocks mvp linq-to-nhibernate

在(web)应用程序中,我实现了MVP模式以分离核心问题。我的演示者使用LINQ-to-NHibernate直接查询数据库,或者有时他们在查询变得复杂时使用查询对象(但我离题了)。

我的一位演示者的简单示例如下(注意:VB.NET不是我的偏好,但是要求这样做):

Public Class CampusListPresenter
    Inherits BasePresenter(Of ICampusListView)

    Public Sub New(ByVal view As ICampusListView)
        MyBase.New(view)
    End Sub

    Public Sub NeedDataSource()

        Using uow As ISession = _sessionManager.OpenSession()

            _view.DataSource = uow.Queryable(Of Campus)() _
            .Cacheable() _
            .AsEnumerable()

        End Using

    End Sub

End Class

(简化)基本演示者类如下:

Public MustInherit Class BasePresenter(Of TView)

    Protected _view As TView

    Protected _sessionManager As ISessionManager

    Public Sub New(ByVal view As TView)
        Guard.Against(view Is Nothing, "view cannot be null.")
        _view = view
    End Sub

    Public WriteOnly Property SessionManager As ISessionManager
        Set(ByVal value As ISessionManager)
            _sessionManager = value
        End Set
    End Property

End Class

我正在尝试使用NUnit和Rhino Mocks对我的演示者(特别是LINQ查询)进行单元测试。在上面的CampusListPresenter的单元测试用例中,我将模拟视图传递给演示者。基本上我想在这个模拟的视图对象上执行断言,以确认Datasouce属性被适当地设置。但是,这始终为空。

我的单元测试的(简化)示例如下(理解我对正确的单元测试相对较新):

<TestFixture()> _
Public Class CampusListPresenterTests

    Dim _realSessionManager As ISessionManager

    <TestFixtureSetUp()> _
    Public Sub TestFixtureSetUp()
        _realSessionManager = DefaultSessionManager.Instance
    End Sub

    Dim _view As ICampusListView
    Dim _fakeSessionManager As ISessionManager

    <SetUp()> _
    Public Sub Setup()
        _view = MockRepository.GenerateMock(Of ICampusListView)()
        _fakeSessionManager = MockRepository.GenerateMock(Of ISessionManager)()
    End Sub

    <Test()> _
    Public Sub NeedDataSource_UsingRealSession_DataSourceIsAssigned()

        'Arrange
        Dim realSession As ISession = _realSessionManager.OpenSession()
        _fakeSessionManager.Expect(Function(sm) sm.OpenSession()).Return(realSession)

        'Act
        Dim presenter As New CampusListPresenter(_view)
        presenter.SessionManager = _fakeSessionManager
        presenter.NeedDataSource()

        'Assert
        _fakeSessionManager.VerifyAllExpectations()
        Assert.AreEqual(_view.DataSource, realSession.Queryable(Of Campus)())

    End Sub

End Class

我实际上设置了我的单元测试以使用内存中的SQLite数据库并在setup / teardown方法中填充/销毁数据,但是上面的例子中已经省略了这一点以简化。

基本上,在这个单元测试中,我从一个模拟的会话管理器(一个用于会话管理的类 - 想想Castle.Facilities.NHibernateIntegration)返回一个真正的NHibernate ISession,这样LINQ-to-NHibernate可以/将实际返回有效的可枚举结果。无论如何在演示者实现中我分配了视图数据源(在NeedDataSource内),但是当我在这个属性上做一个断言时,指定的值总是为空。

任何人都可以帮助我吗?

亲切的问候, 莱恩。

1 个答案:

答案 0 :(得分:1)

模拟的ICampusListView无法保留已分配的数据源对象。以下是两种可能的解决方法。首先,您可以使用存根而不是模拟(有关模拟和存根之间差异的更多背​​景信息,请参阅this帖子):

_view = MockRepository.GenerateStub(Of ICampusListView)()

如果您确实想使用模拟而不是存根,请在测试中的Expect对象上使用VerifyAllExpectationsICampusListView

    'Arrange
    Dim realSession As ISession = _realSessionManager.OpenSession()
    _fakeSessionManager.Expect(Function(sm) sm.OpenSession()).Return(realSession)
    _view.Expect(Function(v) v.SetDataSource(Arg(Of DataSource).Is.Anything))

    'Act
    Dim presenter As New CampusListPresenter(_view)
    presenter.SessionManager = _fakeSessionManager
    presenter.NeedDataSource()

    'Assert
    _fakeSessionManager.VerifyAllExpectations()
    _view.VerifyAllExpectations()
    Assert.AreEqual(_view.DataSource, realSession.Queryable(Of Campus)())