如果我希望单元测试一个表达式作为参数的方法,我应该改变什么?

时间:2014-07-27 11:15:21

标签: c# unit-testing moq automoq

如何为此方法编写单元测试:

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);

但是我无法编译它,如何更改此测试以便模拟生成hamCommentsspamComments的值。

  

错误2&#39; System.Linq.Expressions.Expression&gt;&#39;   不包含&#39; IsSpam&#39;的定义没有扩展方法   &#39; IsSpam&#39;接受第一个类型的参数   &#39;&System.Linq.Expressions.Expression GT;&#39;   可以找到(你错过了使用指令或程序集   引用?)

1 个答案:

答案 0 :(得分:0)

您正在尝试重新创建要在测试中测试的逻辑,我认为这是您的错误。试试这段代码:

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实例的列表,并将它们拆分为不同的分类(垃圾邮件和火腿),因此您只需要{ {1}}返回单个评论列表。

然后由你的单元测试的其余部分来验证你的mockRepository做了它应该做的事情,知道它有10个“垃圾邮件”和10个“火腿”ClassifyComments实例

举个例子,我们假设您的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;
}

修改

好的,我对Moq进行了一些研究,我认为上面的代码就是你如何用Moq做的。