C# 模拟实体中的ICollection属性

C# 模拟实体中的ICollection属性,c#,unit-testing,mocking,moq,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 vi

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

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; }
}
我想使用Moqmocks对其进行单元测试-特别是我想模拟
教师的
.Count
方法。学生
在那里我可以传递任何表达式,它将返回一个数字,表明当前有10个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);
}
[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" });
}
[TestMethod]
[ExpectedException(typeof(TooManyBobsException))]
公共空间不能添加太多的内容()
{
模拟学生=新模拟();
Setup(s=>s.Count(It.IsAny()).Returns(10);
教师=新教师();
teacher.MaxBobs=1;
//将集合设置为模拟-我认为这是我出错的地方
教师。学生=学生。对象;
//下一行应该引发异常,因为只能有一个异常
//鲍勃,但我的模拟收藏说有10个
teacher.AddStudent(newstudent(){Name=“Bob”});
}
我期待我的自定义异常,但我实际得到的是
System.NotSupportedException
,它推断
ICollection
.Count
方法不是虚拟的,因此无法模拟。如何模拟此特定函数


感谢您的帮助!

您不能嘲笑您正在使用的
Count
方法,因为它是一个扩展方法。它不是在
ICollection
上定义的方法
最简单的解决方案是简单地将一个包含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);
教师=新教师();
teacher.MaxBobs=1;
teacher.Students=新集合();
var hasTooManyBobs=false;
尝试
{
teacher.AddStudent(newstudent(){Name=“Bob”});
teacher.AddStudent(newstudent(){Name=“Bob”});
}
捕获(TooManyBobsException)
{
hasTooManyBobs=true;
}
Assert.IsFalse(hasTooManyBobs);

这不应该是
Assert.IsTrue(hasTooManyBobs);
吗?MSTest支持。不需要try-catch块。顺便说一句,moles或fakes框架允许模拟扩展方法。@DanielHilgarth当然!我知道它是这样的,现在可以正常工作了,谢谢。