【问题标题】:Mocking ICollection property in entity在实体中模拟 ICollection 属性
【发布时间】:2013-01-08 13:30:00
【问题描述】:

我正在对我的实体执行一些单元测试,但我在模拟一个属性时有点精神障碍。采取以下实体:

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 模拟对此进行单元测试 - 具体来说,我想模拟 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 方法不是虚拟的,因此不能被模拟。如何模拟这个特定的功能?

任何帮助总是很感激!

【问题讨论】:

    标签: c# unit-testing mocking moq


    【解决方案1】:

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

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

    【讨论】:

    • 附带说明,moles 或 fakes 框架允许模拟扩展方法。
    • @DanielHilgarth 当然!我知道它是这样的,现在按预期工作,谢谢。
    【解决方案2】:

    如果您可以简单地验证是否使用真实集合而不是模拟引发了异常,则无需模拟集合。由于您使用的是 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);
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-12-25
    • 2016-10-19
    • 1970-01-01
    • 2013-01-24
    • 1970-01-01
    • 2017-07-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多