对集合进行排序的方法进行单元测试
Unit test a method that sorts a collection
我有一种基于 属性 对集合进行排序的方法,如下所示:
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);
}
有人建议说这个测试是无效的,因为它设置了一个值然后断言它。
在这种情况下,我该如何编写正确的单元测试?
测试列表是否正确排序在很大程度上是无关紧要的,因为它是一种内置的框架方法(您会假设)已经过框架设计者(在本例中为 Microsoft)测试并证明是正确的。
对此方法的更好测试是确保只返回不在课程 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);
}
你测试的是一个空测试(它测试你构建的列表是否有你刚放在那里的第一个元素)。
在目前的情况下,您的 有同样的问题。它设置了您的存储库的模拟,然后验证模拟 returns 您告诉模拟的信息。
为了有效地测试存储库逻辑,您需要模拟其依赖项,在本例中为 _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();
}
}
注意,我正在将目录上下文注入存储库。这是必需的,以便它可以被嘲笑。另外,请注意我已将您的 LINQ 查询中的 EnrolledDateTime
重命名为 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 进行了降序排序,因此列表中的第一项是 EnrollTime 为“03/30/16 12:50:38 PM”的项。
我有一种基于 属性 对集合进行排序的方法,如下所示:
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);
}
有人建议说这个测试是无效的,因为它设置了一个值然后断言它。
在这种情况下,我该如何编写正确的单元测试?
测试列表是否正确排序在很大程度上是无关紧要的,因为它是一种内置的框架方法(您会假设)已经过框架设计者(在本例中为 Microsoft)测试并证明是正确的。
对此方法的更好测试是确保只返回不在课程 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);
}
你测试的是一个空测试(它测试你构建的列表是否有你刚放在那里的第一个元素)。
在目前的情况下,您的
为了有效地测试存储库逻辑,您需要模拟其依赖项,在本例中为 _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();
}
}
注意,我正在将目录上下文注入存储库。这是必需的,以便它可以被嘲笑。另外,请注意我已将您的 LINQ 查询中的 EnrolledDateTime
重命名为 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 进行了降序排序,因此列表中的第一项是 EnrollTime 为“03/30/16 12:50:38 PM”的项。