如果我想用表达式作为参数进行单元测试,我应该做些什么呢?
本文关键字:单元测试 我应该 做些什么 参数 表达式 如果 | 更新日期: 2023-09-27 18:14:58
如何为这个方法编写单元测试:
public void ClassifyComments()
{
IEnumerable<Comment> hamComments = _commentRepository.FindBy(x => x.IsSpam == false);
IEnumerable<Comment> spamComments = _commentRepository.FindBy(x => x.IsSpam == true);
//....
}
FindBy
方法接受一个表达式作为参数:
public virtual IEnumerable<T> FindBy(Expression<Func<T, bool>> filter)
{
return dbSet.Where(filter).ToList();
}
这是我到目前为止的单元测试:
IEnumerable<Comment> spamComments = Builder<Comment>.CreateListOfSize(10).All()
.With(x => x.Content = "spam spam spam")
.Build();
IEnumerable<Comment> hamComments = Builder<Comment>.CreateListOfSize(10).All()
.With(x => x.Content = "ham ham ham")
.Build();
var mockRepository = new Mock<IGenericRepository<Comment>>();
mockRepository
.Setup(x => x.FindBy(It.Is<Expression<Func<Comment, bool>>>(y => y.IsSpam == true)))
.Returns(spamComments);
mockRepository
.Setup(x => x.FindBy(It.Is<Expression<Func<Comment, bool>>>(y => y.IsSpam == true)))
.Returns(hamComments);
但是我不能编译它,我怎么能改变这个测试,使模拟生成hamComments
和spamComments
的值。
错误2 'System.Linq.Expressions.Expression>'不包含'IsSpam'的定义和没有扩展方法'IsSpam'接受类型为的第一个参数"System.Linq.Expressions.Expression>"可以找到(您是否缺少using指令或程序集?参考?)
您试图在测试中重新创建要测试的逻辑,我认为这是您的错误。试试下面的代码:
IEnumerable<Comment> spamComments = Builder<Comment>.CreateListOfSize(10).All()
.With(x => x.Content = "spam spam spam")
.Build();
IEnumerable<Comment> hamComments = Builder<Comment>.CreateListOfSize(10).All()
.With(x => x.Content = "ham ham ham")
.Build();
// Bring both lists together as one (might be a better way to do this)
IEnumerable<Comment> allComments = spamComments.Union(hamComments);
var mockRepository = new Mock<IGenericRepository<Comment>>();
mockRepository
.Setup(x => x.FindBy(It.Is<Expression<Func<Comment, bool>>>())
.Returns(spamComments);
注意:我不是Moq专家,所以上面的语法可能不是100%正确的
因此,ClassifyComments
方法中的代码的目的是获取混合Comment
实例的列表,并将它们分成不同的分类(spam和ham),因此您只希望mockRepository
返回单个注释列表。
然后由你的单元测试的其余部分来验证你的ClassifyComments
在知道它有10个"垃圾邮件"和10个"火腿"Comment
实例的情况下做了它应该做的事情。
作为一个例子,让我们假设你的ClassifyComments
看起来像这样:
public void ClassifyComments(out IEnumerable<Comment> spam, out IEnumerable<Comment> ham)
{
IEnumerable<Comment> hamComments = _commentRepository.FindBy(x => x.IsSpam == false);
IEnumerable<Comment> spamComments = _commentRepository.FindBy(x => x.IsSpam == true);
//....
// Set the out params
spam = spamComments;
ham = hamComments;
}
你的单元测试应该是这样的:
public void TestClassifyComments() {
IEnumerable<Comment> spamComments = Builder<Comment>.CreateListOfSize(10).All()
.With(x => x.Content = "spam spam spam")
.Build();
IEnumerable<Comment> hamComments = Builder<Comment>.CreateListOfSize(10).All()
.With(x => x.Content = "ham ham ham")
.Build();
// Bring both lists together as one (might be a better way to do this)
IEnumerable<Comment> allComments = spamComments.Union(hamComments);
var mockRepository = new Mock<IGenericRepository<Comment>>();
mockRepository
.Setup(x => x.FindBy(It.Is<Expression<Func<Comment, bool>>>())
.Returns( (Expression<Func<Comment, bool>> predicate => spamComments.Where(predicate));
// Construct the class which has the ClassifyComments method
var sut = ...;
IEnumerable<Comment> ham;
IEnumerable<Comment> spam;
sut.ClassifyComments(out spam, out ham);
Assert.That(spam.Length, Is.EqualTo(10));
Assert.That(ham.Length, Is.EqualTo(10));
}
编辑
好的,我对Moq做了一些研究,我认为上面的代码是你如何用Moq做到这一点。