存储库方法的模拟表达式参数
Mock Expression Parameter to Repository Method
使用最小起订量。我有一个具有以下界面的存储库:
public virtual IEnumerable<TEntity> GetBySpec(ISpecification<TEntity> specification, params string[] includes)
{
IQueryable<TEntity> query = includes.Aggregate<string, IQueryable<TEntity>>(_dbSetQuery, (current, include) => current.Include(include));
return query.Where(specification.SatisfiedBy())
.AsEnumerable<TEntity>();
}
在这种情况下,我使用的是 DirectSpecification:
public sealed class DirectSpecification<TEntity> : Specification<TEntity>
{
Expression<Func<TEntity, bool>> _MatchingCriteria;
public DirectSpecification(Expression<Func<TEntity, bool>> matchingCriteria)
{
_MatchingCriteria = matchingCriteria;
}
public override Expression<Func<TEntity, bool>> SatisfiedBy()
{
return _MatchingCriteria;
}
}
在我调用的实际代码中
var recentlyChanged = _vwPersonRepository.GetBySpec(
new DirectSpecification<vwPerson>(person =>
person.ModifiedDate > modifiedFromDay &&
person.ModifiedDate < modifiedTo));
var recentlyCreated = _vwPersonRepository.GetBySpec(
new DirectSpecification<vwPerson>(person =>
person.CreatedDate > createdFromDay &&
person.CreatedDate < createdTo));
编辑:按照重复的建议,我试过这个:
Container.GetMock<IvwPersonRepository>()
.Setup(p => p.GetBySpec(It.IsAny<ISpecification<vwPerson>>()))
.Returns((Expression<Func<vwPerson, bool>> predicate) =>
items.Where(predicate));
我得到一个
Exception thrown: 'System.Reflection.TargetParameterCountException' in mscorlib.dll
Additional information: Parameter count mismatch.
我的问题因为有 ISpecification 参数而变得复杂,我怎样才能获得正确的参数以便我可以使用谓词?
编辑 2:感谢 Patrick,这是解决方案:
Container.GetMock<IvwPersonRepository>()
.Setup(p => p.GetBySpec(It.IsAny<ISpecification<vwPerson>>(), It.IsAny<string[]>()))
.Returns((ISpecification<vwPerson> specification, string[] includes) =>
items.Where(predicate));
他们的关键是包含 string[] includes
,即使我没有将它作为参数传递,反射也会找到它并期望它在那里。
太棒了!
你编辑的Setup
调用错误,应该是:
Container.GetMock<IvwPersonRepository>()
.Setup(p => p.GetBySpec(It.IsAny<ISpecification<vwPerson>>()))
.Returns((ISpecification<vwPerson> specification) => /* TODO */);
(这是因为传递给 Returns
的参数是传递给正在设置的函数的参数,在本例中是 GetBySpec
。)
我相信(根据您发布的内容)您可以这样做:
Container.GetMock<IvwPersonRepository>()
.Setup(p => p.GetBySpec(It.IsAny<ISpecification<vwPerson>>()))
.Returns((ISpecification<vwPerson> specification) => items.Where(specification.SatisfiedBy()));
但是,您可能会看到使用工厂创建规范的一些好处,这样您就可以模拟它们以避免依赖它们的实现(在上面对 SatisfiedBy
的调用中)。
使用最小起订量。我有一个具有以下界面的存储库:
public virtual IEnumerable<TEntity> GetBySpec(ISpecification<TEntity> specification, params string[] includes)
{
IQueryable<TEntity> query = includes.Aggregate<string, IQueryable<TEntity>>(_dbSetQuery, (current, include) => current.Include(include));
return query.Where(specification.SatisfiedBy())
.AsEnumerable<TEntity>();
}
在这种情况下,我使用的是 DirectSpecification:
public sealed class DirectSpecification<TEntity> : Specification<TEntity>
{
Expression<Func<TEntity, bool>> _MatchingCriteria;
public DirectSpecification(Expression<Func<TEntity, bool>> matchingCriteria)
{
_MatchingCriteria = matchingCriteria;
}
public override Expression<Func<TEntity, bool>> SatisfiedBy()
{
return _MatchingCriteria;
}
}
在我调用的实际代码中
var recentlyChanged = _vwPersonRepository.GetBySpec(
new DirectSpecification<vwPerson>(person =>
person.ModifiedDate > modifiedFromDay &&
person.ModifiedDate < modifiedTo));
var recentlyCreated = _vwPersonRepository.GetBySpec(
new DirectSpecification<vwPerson>(person =>
person.CreatedDate > createdFromDay &&
person.CreatedDate < createdTo));
编辑:按照重复的建议,我试过这个:
Container.GetMock<IvwPersonRepository>()
.Setup(p => p.GetBySpec(It.IsAny<ISpecification<vwPerson>>()))
.Returns((Expression<Func<vwPerson, bool>> predicate) =>
items.Where(predicate));
我得到一个
Exception thrown: 'System.Reflection.TargetParameterCountException' in mscorlib.dll
Additional information: Parameter count mismatch.
我的问题因为有 ISpecification 参数而变得复杂,我怎样才能获得正确的参数以便我可以使用谓词?
编辑 2:感谢 Patrick,这是解决方案:
Container.GetMock<IvwPersonRepository>()
.Setup(p => p.GetBySpec(It.IsAny<ISpecification<vwPerson>>(), It.IsAny<string[]>()))
.Returns((ISpecification<vwPerson> specification, string[] includes) =>
items.Where(predicate));
他们的关键是包含 string[] includes
,即使我没有将它作为参数传递,反射也会找到它并期望它在那里。
太棒了!
你编辑的Setup
调用错误,应该是:
Container.GetMock<IvwPersonRepository>()
.Setup(p => p.GetBySpec(It.IsAny<ISpecification<vwPerson>>()))
.Returns((ISpecification<vwPerson> specification) => /* TODO */);
(这是因为传递给 Returns
的参数是传递给正在设置的函数的参数,在本例中是 GetBySpec
。)
我相信(根据您发布的内容)您可以这样做:
Container.GetMock<IvwPersonRepository>()
.Setup(p => p.GetBySpec(It.IsAny<ISpecification<vwPerson>>()))
.Returns((ISpecification<vwPerson> specification) => items.Where(specification.SatisfiedBy()));
但是,您可能会看到使用工厂创建规范的一些好处,这样您就可以模拟它们以避免依赖它们的实现(在上面对 SatisfiedBy
的调用中)。