Я собираюсь протестировать сервис, использующий Entity Framework 6.
Пример сценария, он будет иметь сущность «Блог и публикация», «Блог» будет иметь ноль или более сообщений. В методе сервиса он возвращает список сущностей, которые имеют заголовок блога и заголовок первого поста этого блога. Похоже ниже.
public class BlogService
{
private IBloggingContext _context;
public BlogService(IBloggingContext context)
{
_context = context;
}
public List<BlogPostSumarry> GeBlogSummary()
{
var query = from b in _context.Blogs
orderby b.Name
select new BlogPostSumarry
{
BlogTitle = b.Name,
PostTitle = b.Posts.FirstOrDefault().Title
};
return query.ToList();
}
}
}
Метод модульных испытаний
[Test]
public void GeBlogSummary_WhenMatchFound()
{
var post = new List<Post>()
{
new Post() {PostId=45, Title="abc"}
};
var data = new List<Blog>
{
new Blog { Name = "BBB" },
new Blog { Name = "ZZZ" },
new Blog { Name = "AAA" },
}.AsQueryable();
var mockSet = new Mock<DbSet<Blog>>();
mockSet.As<IQueryable<Blog>>().Setup(m => m.Provider).Returns(data.Provider);
mockSet.As<IQueryable<Blog>>().Setup(m => m.Expression).Returns(data.Expression);
mockSet.As<IQueryable<Blog>>().Setup(m => m.ElementType).Returns(data.ElementType);
mockSet.As<IQueryable<Blog>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
var mockContext = new Mock<BloggingContext>();
mockContext.Setup(c => c.Blogs).Returns(mockSet.Object);
var service = new BlogService(mockContext.Object);
var blogs = service.GeBlogSummary();
Assert.AreEqual(3, blogs.Count);
Assert.AreEqual("AAA", blogs[0].BlogTitle);
Assert.AreEqual("BBB", blogs[1].BlogTitle);
Assert.AreEqual("ZZZ", blogs[2].BlogTitle);
}
Модульный тест, который я использую, чтобы высмеивать использование DbContext и DbSet в данных памяти. Проблема заключается в том, что в случае, если в блогах нет ни одного пост-модульного теста, будет выдано исключение нулевой ссылки, где, как и в реальном сценарии (база данных), он работает нормально. Это потому, что в случае с памятью это Linq to Object, где, как и в EF, это Linq to Entity.
Например, если я меняю метод, как показано ниже, он работает UnitTest
public List<BlogPostSumarry> GeBlogSummary()
{
var query = from b in _context.Blogs
orderby b.Name
select new BlogPostSumarry
{
BlogTitle = b.Name,
//Manually checks for null validation works but any approach without change code for sack of unit test
PostTitle = b.Posts.Any() ? b.Posts.FirstOrDefault().Title : null
};
return query.ToList();
}
Однажды подход - это изменить запрос linq для проверки на ноль, но я думаю, что это не очень хороший подход. Если да, то как я могу выполнить тест?