用Moq模拟NHibernate的JoinAlias

本文关键字:JoinAlias NHibernate 模拟 Moq | 更新日期: 2023-09-27 18:16:24

我有以下存储库代码,它将根据ID值返回Company对象,并在标准Company表和名为ExternalCompany的附加表中进行搜索。

public Company FindByIdJoin(long id)
{
    ExternalCompany xcomp = null;
    return Session.QueryOver<Company>()
        .Where(p => p.ObjectId == id)
        .JoinAlias(p => p.ExternalCompanies, () => xcomp, JoinType.LeftOuterJoin)
        .SingleOrDefault<Company>();
}

代码返回我期望的值。然而,我遇到的麻烦是在编写一个Moq单元测试来处理JoinAlias调用。

在一个更简单的方法中,称为FindById,代码基本上是相同的,只是没有JoinAlias的行。这个简单方法的单元测试是:

[Test]
public void FindById_returns_Company_for_valid_Id()
{
    // Arrange
    Mock<IQueryOver<Company, Company>> mockQueryOver = new Mock<IQueryOver<Company, Company>>();
    mockQueryOver.Setup(x => x.Where(It.IsAny<Expression<Func<Company, bool>>>())).Returns(mockQueryOver.Object);
    mockQueryOver.Setup(x => x.SingleOrDefault()).Returns(fake_Company);
    // Act
    var result = _repository.FindById(fake_Company.ObjectId);
    // Assert
    Assert.IsNotNull(result);
    mockQueryOver.VerifyAll();
}

这个测试可以正常工作并且没有问题通过(fake_Company和_repository在其他地方定义)。

问题是试图把FindByIdJoin调用的测试放在一起。我试过使用这样的额外设置行(在Where和SingleOrDefault设置行之间):

mockQueryOver.Setup(x => x.JoinAlias(It.IsAny<Expression<Func<Company>>>(), It.IsAny<Expression<Func<ExternalCompany>>>(), JoinType.LeftOuterJoin)).Returns(mockQueryOver.Object);

系统告诉我"IQueryOver的最佳重载方法匹配…有一些无效参数。"

所以,我尝试了一些其他的设置,但没有找到一个可行的模式。

我的问题是:什么设置参数将JoinAlias工作,以便我可以正确地测试FindByIdJoin方法?谢谢!

用Moq模拟NHibernate的JoinAlias

您正在使用的JoinAlias的特定过载是

IQueryOver<TRoot, TSubType> JoinAlias(
                                Expression<Func<TSubType, object>> path, 
                                Expression<Func<object>> alias, 
                                JoinType joinType);

所以,你的设置需要匹配这个。根据您设置IQueryOver模拟的方式,正确的设置应该是

mockQueryOver.Setup(x => x.JoinAlias(
                               It.IsAny<Expression<Func<Company, object>>>(), 
                               It.IsAny<Expression<Func<object>>>(),
                               JoinType.LeftOuterJoin))
             .Returns(mockQueryOver.Object);

行为测试不应该使用最小起订量吗?这样的数据访问测试似乎是依赖于状态的,我认为对这样一个被测系统使用模拟对象是多余的。