实体中的Mocking collection属性

本文关键字:collection 属性 Mocking 实体 | 更新日期: 2023-09-27 17:50:57

我正在对我的实体执行一些单元测试,并且我在模拟属性时遇到了一点心理障碍。以以下实体为例:

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的学生。如果是这样,那么我将引发一个自定义异常,表示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 mocks对其进行单元测试-特别是我想模拟Teacher.Students.Count方法,我可以将其传递任何表达式,它将返回一个数字,表明目前有10个bob分配给该教师。我是这样设置的:

[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,这推断ICollection.Count方法不是虚拟的,因此不能被嘲笑。如何模拟这个特定的函数?

任何帮助总是感激!

实体中的Mocking collection属性

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

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

当您可以使用实际集合而不是模拟来验证异常是否被抛出时,就不需要模拟集合了。由于使用的是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);