我想使用 Moq 或 RhinoMocks 模拟此接口,以验证是否将正确的表达式作为参数传递(并愿意切换到可以支持此功能的任何其他开源模拟库):
完整源代码:
public class Record
{
public int RecordId { get; set; }
}
public interface IRepository
{
void DeleteRecordsByFilter(Expression<Func<Record, bool>> filter);
}
public class MyClass
{
private readonly IRepository _repo;
public MyClass(IRepository repo)
{
_repo = repo;
}
public void DeleteRecords(int recordId)
{
_repo.DeleteRecordsByFilter(x => x.RecordId.Equals(recordId));
}
}
[TestFixture]
public class MyFixture
{
[Test]
public void DeleteRecordsShouldCallDeleteRecordsByFilterOnRepo()
{
const int recordId = 10;
var repo = new Mock<IRepository>();
repo.Setup(method => method.DeleteRecordsByFilter(x => x.RecordId.Equals(recordId)));
var sut = new MyClass(repo.Object);
sut.DeleteRecords(recordId);
repo.Verify(method => method.DeleteRecordsByFilter(x => x.RecordId.Equals(recordId)));
}
}
当我执行单元测试时,它失败并出现错误:
Moq.MockException :预期对模拟至少调用一次,
但从未执行过: method => method.DeleteRecordsByFilter(x =>
x.RecordId.Equals(10))
配置设置: method => method.DeleteRecordsByFilter(x =>
x.RecordId.Equals(10)), Times.Never
执行的调用: IRepository.DeleteRecordsByFilter(x =>
x.RecordId.Equals(value(MyClass+c__DisplayClass0).recordId))
As per 这个帖子 https://stackoverflow.com/questions/5032865/how-do-linq-expressions-determine-equality,比较Expression
可能非常脆弱,因为默认值是通过引用的,并且需要寻找替代方案。但是,使用引用的方法,即通过简单ToString()
表达式的比较Body
,您可以像这样验证表达式:
var _mock = new Mock<IInterfaceToBeMocked>();
// "Act" step -> invoke your CUT, which in turn calls the mocked interface dependency
// (Obviously your CUT will do this, but just to prove the point ...)
_mock.Object.DeleteRecordsByFilter(x => x.RecordId.Equals(10));
// Back to the unit test
Expression<Func<Record, bool>> goodComparison = x => x.RecordId.Equals(10);
Expression<Func<Record, bool>> badComparison = x => x.RecordId > 10 && x.RecordId < 12;
_mock.Verify(m => m.DeleteRecordsByFilter(
It.Is<Expression<Func<Record, bool>>>(ex => ex.Body.ToString() == goodComparison.Body.ToString())),
Times.Once);
_mock.Verify(m => m.DeleteRecordsByFilter(
It.Is<Expression<Func<Record, bool>>>(ex => ex.Body.ToString() == badComparison.Body.ToString())),
Times.Never());
(i.e Moq
保留类型的调用参数列表Expression
,就像可以在 a 中使用的任何其他类型的参数一样Verify
or Setup
)
Edit
上面的方法适用于表达式中没有外部变量或闭包变量的简单情况,因此两个表达式等效地序列化。当 CUT 将相同的表达式实例传递给依赖项时,来自 @Oliver 的引用相等将起作用。但在一般情况下,您需要以某种方式确定两个表达式是否等效,例如使用一组已知的输入和输出调用两个表达式(但这更多地与表达式/函数/Lambda 的等价性问题有关 - 而不是真正的 Moq 问题)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)