具有精确表达式的最小起订量<Func<TEntity, bool>>
Moq with exact Expression<Func<TEntity, bool>>
我正在尝试测试存储库的 Get 方法。签名如下:
public virtual IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "")
该方法通常按以下方式调用:
Department targetDepartment =
_departmentRepository.Get(department => department.Id == departmentId).FirstOrDefault();
它适用于真实数据,当我尝试将此方法设置为 return 具有特定 lambda 的特定 'Department' 时,问题就开始了。
到目前为止,我已经尝试了很多方法来模拟它,这里是其中的一些:
1)
Expression<Func<Department, bool>> filterExpression2 = d => d.Id == DepartmentId;
_departmentRepositoryMock.Setup(repo => repo.Get(
It.Is<Expression<Func<Department, bool>>>(y => filterExpression2.Compile()(firstDepartment)),
null,
It.IsAny<string>()))
.Returns(new List<Department>() { firstDepartment }.AsQueryable());
2)
Expression<Func<Department, bool>> filterExpression2 = d => d.Id == DepartmentId;
_departmentRepositoryMock.Setup(repo => repo.Get(
It.IsAny<Expression<Func<Department, bool>>>(),
null,
It.IsAny<string>()))
.Returns(new List<Department>() { firstDepartment }.Where(filterExpression2.Compile()).AsQueryable());
我看到了很多类似的问题,但不知何故 none 有帮助。
我想做的是根据发送到 lambda 的 'Id' 参数强制模拟存储库到 return 特定部门。
我知道许多使用 It.IsAny
的响应,但这不是我想要的,因为它会触发对传递给 Get 方法的任何表达式的匹配。
任何人都可以帮助我,或者至少将我推向正确的方向吗?
尝试了以下最小示例并能够通过测试。注意设置和returns.
[TestClass]
public class UnitTest11 {
[TestMethod]
public void TestMethod1() {
//Arrange
//fake data
var list = Enumerable.Range(1, 10).Select(id => new Department { Id = id }).ToList();
var mock = new Mock<IRepository<Department>>();
mock
.Setup(repo => repo.Get(
It.IsAny<Expression<Func<Department, bool>>>(),
null,
It.IsAny<string>())
)
.Returns(
(
Expression<Func<Department, bool>> filter,
Func<IQueryable<Department>, IOrderedQueryable<Department>> orderBy,
string includeProperties
) => {
var func = filter.Compile();
var result = list.Where(func);
if (orderBy != null) {
result = orderBy(result.AsQueryable());
}
return result;
}
);
var sut = new MyClass(mock.Object);
var departmentId = 2;
//Act
var actual = sut.GetDepartment(departmentId);
//Assert
Assert.IsNotNull(actual);
Assert.AreEqual(actual, list[departmentId - 1]);
}
public class MyClass {
private readonly IRepository<Department> _departmentRepository;
public MyClass(IRepository<Department> repository) {
this._departmentRepository = repository;
}
public Department GetDepartment(int departmentId) {
Department targetDepartment = _departmentRepository.Get(department => department.Id == departmentId).FirstOrDefault();
return targetDepartment;
}
}
public class Department {
public int Id { get; set; }
}
public interface IRepository<TEntity> {
IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = ""
);
}
}
我正在尝试测试存储库的 Get 方法。签名如下:
public virtual IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "")
该方法通常按以下方式调用:
Department targetDepartment =
_departmentRepository.Get(department => department.Id == departmentId).FirstOrDefault();
它适用于真实数据,当我尝试将此方法设置为 return 具有特定 lambda 的特定 'Department' 时,问题就开始了。
到目前为止,我已经尝试了很多方法来模拟它,这里是其中的一些:
1)
Expression<Func<Department, bool>> filterExpression2 = d => d.Id == DepartmentId;
_departmentRepositoryMock.Setup(repo => repo.Get(
It.Is<Expression<Func<Department, bool>>>(y => filterExpression2.Compile()(firstDepartment)),
null,
It.IsAny<string>()))
.Returns(new List<Department>() { firstDepartment }.AsQueryable());
2)
Expression<Func<Department, bool>> filterExpression2 = d => d.Id == DepartmentId;
_departmentRepositoryMock.Setup(repo => repo.Get(
It.IsAny<Expression<Func<Department, bool>>>(),
null,
It.IsAny<string>()))
.Returns(new List<Department>() { firstDepartment }.Where(filterExpression2.Compile()).AsQueryable());
我看到了很多类似的问题,但不知何故 none 有帮助。
我想做的是根据发送到 lambda 的 'Id' 参数强制模拟存储库到 return 特定部门。
我知道许多使用 It.IsAny
的响应,但这不是我想要的,因为它会触发对传递给 Get 方法的任何表达式的匹配。
任何人都可以帮助我,或者至少将我推向正确的方向吗?
尝试了以下最小示例并能够通过测试。注意设置和returns.
[TestClass]
public class UnitTest11 {
[TestMethod]
public void TestMethod1() {
//Arrange
//fake data
var list = Enumerable.Range(1, 10).Select(id => new Department { Id = id }).ToList();
var mock = new Mock<IRepository<Department>>();
mock
.Setup(repo => repo.Get(
It.IsAny<Expression<Func<Department, bool>>>(),
null,
It.IsAny<string>())
)
.Returns(
(
Expression<Func<Department, bool>> filter,
Func<IQueryable<Department>, IOrderedQueryable<Department>> orderBy,
string includeProperties
) => {
var func = filter.Compile();
var result = list.Where(func);
if (orderBy != null) {
result = orderBy(result.AsQueryable());
}
return result;
}
);
var sut = new MyClass(mock.Object);
var departmentId = 2;
//Act
var actual = sut.GetDepartment(departmentId);
//Assert
Assert.IsNotNull(actual);
Assert.AreEqual(actual, list[departmentId - 1]);
}
public class MyClass {
private readonly IRepository<Department> _departmentRepository;
public MyClass(IRepository<Department> repository) {
this._departmentRepository = repository;
}
public Department GetDepartment(int departmentId) {
Department targetDepartment = _departmentRepository.Get(department => department.Id == departmentId).FirstOrDefault();
return targetDepartment;
}
}
public class Department {
public int Id { get; set; }
}
public interface IRepository<TEntity> {
IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = ""
);
}
}