单元测试排序集合的方法(Unit test a method that sorts a collec

2019-09-28 10:56发布

我有一个排序基于这样的属性集合的方法:

public List<Student> GetAllStudents()
{
    return _studentCatalogContext.Student.Where(x => (x.Course != 2 && x.Course != 6))
                                 .OrderByDescending(x => x.EnrollDateTime).ToList();
}

这样的想法是有,在这种情况下,最近招收的学生第一。

由于该方法调用的结果将是一个排序列表与最新的招生首先我写了这样一个测试:

[TestMethod]
public void Calling_GetAllStudents_ReturnsSortedListOfStudents()
{
    var studentsList = new List<Student> {
    new Student {
                     Id = "123",
                     EnrollTime = "02/22/16 14:06:56 PM",
                     Course = 1
                 },
     new Student {
                     Id = "456",
                     EnrollTime = "03/30/16 12:50:38 PM",
                     Course = 3
                 }
                 };

    _studnentRepository.Setup(x=>x.GetAllStudents()).Returns(studentsList);

    Assert.AreEqual("02/22/16 14:06:56 PM", studentsList[0].EnrollTime);
}

它已经表明,这个测试确实不是,它设置一个值有效,然后断言就可以了。

我怎么会写在这种情况下,正确的单元测试?

Answer 1:

测试某列表正确排序基本上是无能为力的,因为它是(你会以为)已经由框架设计师(微软在这种情况下)测试,并证明是正确的内置框架方法。

这种方法的更好的测试将确保不会在课返回谁2或6,只有学生,因为这是内部的自定义逻辑Where方法。

所以,你的测试可能是这样的:

[TestMethod]
public void Calling_GetAllStudents_ReturnsSortedListOfStudents()
{
    var studentsList = new List<Student> {
    new Student {
                     Id = "123",
                     EnrollTime = "02/22/16 14:06:56 PM",
                     Course = 1
                 },
     new Student {
                     Id = "456",
                     EnrollTime = "03/30/16 12:50:38 PM",
                     Course = 2
                 }
                 };

    // mock out student repository to return list    

    var studentsList = _studentRepository.GetAllStudents();

    Assert.AreEqual(1, studentsList.Count);
    Assert.AreEqual("123", studentsList[0].Id);
}


Answer 2:

你测试,因为它代表是一个空测试(测试当你构建的列表中有你只是把在那里的第一个元素)。

在它的当前形式,你接受的答案有同样的问题。 它设置了您的存储库的实体模型,然后将验证模拟的回报,你已经告诉模拟的信息。

为了有效地测试存储库的逻辑,你需要模拟它的依赖,在这种情况下是_studentCatalogContext 。 既然你有没有在你的问题提供了这一点,我将承担以下类:

public class Student {
    public string Id {get;set;}           // Weird this is a string not int
    public string  EnrollTime {get;set;}  // Weird this is a string not date
    public int Course  {get;set;}
}

public class StudentCatalogContext : DbContext
{
    public virtual IDbSet<Student> Student { get; set; }
}

public class StudentRepository
{
    private StudentCatalogContext _studentCatalogContext;
    public StudentRepository(StudentCatalogContext context)
    {
        _studentCatalogContext = context;
    }
    public List<Student> GetAllStudents()
    {
        return _studentCatalogContext.Student.Where(x => (x.Course != 2 && x.Course != 6))
                                     .OrderByDescending(x => x.EnrollTime).ToList();
    }
}

请注意,我注射目录上下文连接到存储库。 这是必需的,以便它可以被嘲笑。 另外,请注意,我已经改名EnrolledDateTime在LINQ查询EnrollTime使其与您的代码示例的其他部分相匹配。

如下此代码可以然后进行测试:

// Construct the data to be returned by the student set mock.
// Note, you don't want this to be in the order that you're expecting
// otherwise, how do you know if it's been sorted...
var studentData = new List<Student> {
    new Student {
                     Id = "123",
                     EnrollTime = "02/22/16 14:06:56 PM",
                     Course = 1
                 },
     new Student {
                     Id = "456",
                     EnrollTime = "03/30/16 12:50:38 PM",
                     Course = 3
                 }
}.AsQueryable();

// Setup a mock of the student set, which returns the canned data
// prepared above
var dbSetMock = new Mock<IDbSet<Student>>();
dbSetMock.Setup(m => m.Provider).Returns(studentData.Provider);
dbSetMock.Setup(m => m.Expression).Returns(studentData.Expression);
dbSetMock.Setup(m => m.ElementType).Returns(studentData.ElementType);
dbSetMock.Setup(m => m.GetEnumerator()).Returns(studentData.GetEnumerator());

// Create a mock of the catalog context that returns
// the mocked set prepared above
var contextMock = new Mock<StudentCatalogContext>();
contextMock.Setup(x=>x.Student).Returns(dbSetMock.Object);

// Create the system under test, injecting the mock context
var repo = new StudentRepository(contextMock.Object);

// Call the method that we're actually testing
var fetchedData = repo.GetAllStudents();

// Validate that the information returned is what we're expecting
Assert.AreEqual("02/22/16 14:06:56 PM", fetchedData[0].EnrollTime);

值得指出的是,上面的测试失败。 这是因为被测代码排序EnrollTime下降,所以在列表中的第一个项目是一个以“16年3月30日下午十二时50分38秒”的EnrollTime



文章来源: Unit test a method that sorts a collection