1

我使用通用存储库来访问 C# 中的数据,其方法签名是这样的:

public virtual IEnumerable<TEntity> Get(
    Expression<Func<TEntity, bool>> filter = null,
    Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
    string includeProperties = "")

然后通过以下方式在 MVC 控制器(例如)中使用它

var users = UnitOfWork.UserRepository.Get(
    u => u.Id == userId, null, "CreatedEmployer,CreatedEmployer.CreatedByUser");

var checkUser = UnitOfWork.UserRepository.Get(u => u.UserName == email)
                                         .FirstOrDefault();

我希望能够使用 RhinoMocks 模拟这些调用,并根据被调用的表达式接收特定结果。下面的伪代码演示了我想要实现的目标,例如

UnitOfWork.UserRepository.Expect(
    u => u.Get(Arg<Expression<Func<User, bool>>>.Matches(u.UserName == "jim")))
                         .Return(new List<User>() { userJim });

UnitOfWork.UserRepository.Expect(
    u => u.Get(Arg<Expression<Func<User, bool>>>.Matches(u.UserName == "jo left ages ago")))
                         .Return(new List<User>() );

我曾尝试使用 .WhenCalled 但它似乎没有我想要的行为,即在匹配提供的确切提供的表达式时,返回一些特定数据:

.WhenCalled(invocation => {
    var predicate = invocation.Arguments.First() as Expression<Func<User, bool>>;
    ... Do something here
})

我已经在互联网上搜索了一段时间,但还没有找到一个像样的解决方案,大多数解决方案都包括忽略参数,只要你只在一个方法中调用 repo 一次,例如

UserRepository.Expect(u => u.Get()).IgnoreArguments()
              .Return(new List<User> { CurrentUser });

这现在被证明是不够的,我需要一些更强大和更具体的东西。我只对第一个论点真正感兴趣。我需要解决上述问题,但如果 R​​hinoMocks 不存在解决方案,那么我会对任何更容易实现测试表达式的模拟框架感兴趣。

4

2 回答 2

0

我已经使用 Moq回答了类似的问题。您可以对 Rhino 使用相同的方法。

关键是使用真实的(或模拟的)数据集,并针对它运行表达式。

于 2013-09-04T14:55:40.673 回答
0

这是对 Sunny 提出的解决方案的改编。感谢他的建议和指导 RhinoMocks 的解决方案。

对于所有测试,您都有一个名为的对象,它是您对存储库的任何调用可能返回的所有数据。就我而言,这是用户数据集:

List<User> users = new List<User>();

然后在每次安排时添加新用户

users.Add(new User() { username="jim" });
users.Add(new User() { username="jo left ages ago" });

然后你调用一次Expect。这会设置对存储库的任何调用以查询您提供的数据。由于某种原因,这不适用于两次调用期望。对 Rhino Mocks 来说,它似乎只显示了一个调用:

baseController.UnitOfWork.UserRepository.Expect(u => u.Get(Arg<Expression<Func<User, bool>>>.Is.Anything, Arg<Func<IQueryable<User>, IOrderedQueryable<User>>>.Is.Anything, Arg<string>.Is.Anything))
    .WhenCalled(invocation =>
        {
        var predicate = invocation.Arguments.First() as Expression<Func<User, bool>>;
        var query = predicate.Compile();
        invocation.ReturnValue = users.Where(query);
        });

顺便说一句,它仍然不适合调用 SpecFlow 的 Given 语句设置期望的方式。您将什么自然陈述与设置 Expect 相关联?但它确实回答了我原来的问题。

于 2013-09-05T08:37:32.307 回答