2

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

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

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

错误 2“System.Linq.Expressions.Expression>”不包含“IsSpam”的定义,并且找不到接受“System.Linq.Expressions.Expression>”类型的第一个参数的扩展方法“IsSpam”(你是缺少 using 指令或程序集引用?)

4

1 回答 1

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

注意:我不是起订量专家,所以上面的语法可能不是 100% 正确

因此,您ClassifyComments方法中代码的目的是获取混合Comment实例列表并将它们分成不同的分类(垃圾邮件和火腿),因此您只希望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 做到这一点的。

于 2014-07-27T15:02:09.610 回答