模拟实体中的ICollection属性

时间:2013-01-08 13:30:00

标签: c# unit-testing mocking moq

我正在对我的实体进行一些单元测试,并且我有一些精神块嘲弄一个属性。采取以下实体:

public class Teacher
{
    public int MaxBobs { get; set; }
    public virtual ICollection<Student> Students { get; set; }
}

public class Student
{
    public string Name { get; set; }
    public virtual Teacher Teacher { get; set; }
}

我在Teacher上有一个名为AddStudent的方法,该方法首先检查教师是否有太多被称为Bob的学生。如果是这样,那么我提出一个自定义异常,说太多了。该方法如下所示:

public void AddStudent(Student student)
{
    if (student.Name.Equals("Bob"))
    {
        if (this.Students.Count(s => s.Name.Equals("Bob")) >= this.MaxBobs)
        {
            throw new TooManyBobsException("Too many Bobs!!");
        }
    }

    this.Students.Add(student);
}

我想使用 Moq 模拟对此进行单元测试 - 具体来说我想模仿.Count Teacher.Students方法,我可以将任何表达式传递给它{'}}将返回一个数字,表示目前有10个Bobs分配给该教师。我这样设置:

[TestMethod]
[ExpectedException(typeof(TooManyBobsException))]
public void Can_not_add_too_many_bobs()
{
    Mock<ICollection<Student>> students = new Mock<ICollection<Student>>();
    students.Setup(s => s.Count(It.IsAny<Func<Student, bool>>()).Returns(10);

    Teacher teacher = new Teacher();
    teacher.MaxBobs = 1;

    // set the collection to the Mock - I think this is where I'm going wrong
    teacher.Students = students.Object; 

    // the next line should raise an exception because there can be only one
    // Bob, yet my mocked collection says there are 10
    teacher.AddStudent(new Student() { Name = "Bob" });
}

我期待我的自定义异常,但我实际得到的是System.NotSupportedException,它推断.Count ICollection方法不是虚拟的,因此无法模拟。我如何模拟这个特定的功能?

任何帮助总是受到赞赏!

2 个答案:

答案 0 :(得分:6)

您无法模拟正在使用的Count方法,因为它是一种扩展方法。它不是ICollection<T>上定义的方法 最简单的解决方案是简单地将一个包含10个bobs的列表分配给Students属性:

teacher.Students = Enumerable.Repeat(new Student { Name = "Bob" }, 10)
                             .ToList();

答案 1 :(得分:0)

当您可以简单地验证是否使用真实集合而不是模拟抛出异常时,无需模拟集合。当您使用MsTest而不是NUnit时,您不能简单地添加ExpectedException属性来验证是否抛出了异常,但您可以执行以下操作:

Teacher teacher = new Teacher();
teacher.MaxBobs = 1;

teacher.Students = new Collection<Student>(); 

var hasTooManyBobs = false;
try 
{
    teacher.AddStudent(new Student() { Name = "Bob" });
    teacher.AddStudent(new Student() { Name = "Bob" });
}
catch(TooManyBobsException)
{
    hasTooManyBobs = true;
}

Assert.IsFalse(hasTooManyBobs);