1

我尝试使用 Moq 对使用 DetachedCriteria 类的存储库上的方法进行单元测试。但是我遇到了一个问题,即我实际上无法模拟内置的内部 Criteria 对象。有没有办法模拟分离的标准?

测试方法

        [Test]
        [Category("UnitTest")]
        public void FindByNameSuccessTest()
        {          
            //Mock hibernate here
            var sessionMock = new Mock<ISession>();
            var sessionManager = new Mock<ISessionManager>();
            var queryMock = new Mock<IQuery>();
            var criteria = new Mock<ICriteria>();
            var sessionIMock = new Mock<NHibernate.Engine.ISessionImplementor>();

            var expectedRestriction = new Restriction {Id = 1, Name="Test"};

            //Set up expected returns
            sessionManager.Setup(m => m.OpenSession()).Returns(sessionMock.Object);
            sessionMock.Setup(x => x.GetSessionImplementation()).Returns(sessionIMock.Object);

            queryMock.Setup(x => x.UniqueResult<SopRestriction>()).Returns(expectedRestriction);

            criteria.Setup(x => x.UniqueResult()).Returns(expectedRestriction);

            //Build repository            
            var rep = new TestRepository(sessionManager.Object);

            //Call repostitory here to get list
            var returnR = rep.FindByName("Test");


            Assert.That(returnR.Id == expectedRestriction.Id);
        }

存储库类

public class TestRepository
{
    protected readonly ISessionManager SessionManager;

    public virtual ISession Session
    {
        get { return SessionManager.OpenSession(); }
    }

    public TestRepository(ISessionManager sessionManager)
    {
    }


    public SopRestriction FindByName(string name)
    {

        var criteria = DetachedCriteria.For<Restriction>().Add<Restriction>(x => x.Name == name)
        return criteria.GetExecutableCriteria(Session).UniqueResult<T>();
    }

}

注意我在这里也使用“NHibernate.LambdaExtensions”和“Castle.Facilities.NHibernateIntegration”。任何帮助将不胜感激。

本质上,我在返回的对象的断言上得到了一个空引用异常。因此,我假设我没有正确连接标准。但我认为我不能这样做,因为标准是在我的存储库中创建的分离标准的私有字段!

4

2 回答 2

5

老实说,我很久以前就放弃了尝试对任何涉及数据库的东西进行单元测试。

启动内存中的 Sqlite 数据库并运行实际测试要容易得多。或者,如果您希望针对真实数据库运行它们,那么只需将它们移动到您的集成测试中,这些测试只有在您签入源代码控制时才会运行。

于 2010-06-11T14:21:33.060 回答
1

我认为您错过了在这种情况下使用嘲笑的意义。你要模拟的是方法

public SopRestriction FindByName(string name)
{
    ...
}

因此,您可以返回任何SopRestriction您想要的类型,而不必担心它正在查询 NHibernate。

模拟任何类型的数据上下文是没有意义的,因为你永远不会获得任何价值。

最简单的方法是从 TestRepository 中提取一个接口,例如 ITestRepository,然后使依赖关系图的其余部分依赖于 ITestRepository,您可以在单元测试中轻松地模拟存储库本身。

跟进:关于您想要验证存储库中的方法调用的回复,我建议将所有 NHibernate 特定用法包装到方法本身中,这些方法本身没有任何类型的参数或 NHibernate 特定的返回,因此您可以模拟这些方法,只是期望它们起作用。这就是为什么在这个阶段单元测试价值较低的原因,因为您不会获得太多收益。有了你所说的,我根本不会嘲笑它们,而是会让它们成为触及数据库或做他们需要做的事情的完整“集成”测试。我仍然认为这些是单元测试,即使 TDD 纯粹主义者会说它们是集成测试。

于 2010-06-11T16:50:53.250 回答