我尝试使用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”。任何帮助将不胜感激。
基本上我在返回的对象的断言上得到一个空引用异常。因此,我假设我没有正确连接标准。但我认为我不能这样做,因为标准是在我的存储库中创建的Detached Criteria的私有字段!
答案 0 :(得分:5)
老实说,我很久以前就试图对触及数据库的任何东西进行单元测试。
在内存中调用Sqlite数据库并运行实际测试要容易得多。或者,如果您希望针对真实数据库运行它们,那么只需将它们移动到集成测试中,这些集成测试仅在您签入源代码控制时才会运行。
答案 1 :(得分:1)
我认为你错过了在这种情况下使用嘲讽的观点。你想要模拟的是方法
public SopRestriction FindByName(string name)
{
...
}
那么你可以返回你想要的任何类型的SopRestriction
,而不用担心它会查询NHibernate。
模仿任何类型的datacontext是没有意义的,因为你永远不会获得任何价值。
最简单的方法是从TestRepository中提取一个接口,就像ITestRepository一样,然后使依赖图的其余部分依赖于ITestRepository,你可以在单元测试中轻松地模拟存储库本身。
跟进:关于您想要验证存储库中的方法调用的响应,我建议将所有NHibernate特定用法包装到没有任何类型参数的方法本身或返回那是特定于NHibernate的,那么你就可以模拟这些方法并期望它们能够工作。这就是为什么在这个阶段单元测试的价值不高,因为你没有获得太多收益。用你所说的我根本不会嘲笑它们,但会使它们完全“集成”测试,触及数据库或做他们需要做的事情。我仍然认为这些是单元测试,即使TDD纯粹主义者会说他们是集成测试。