2014-11-20 3 views
3

Я новичок в Moq. Я выполняю модульное тестирование проекта Entity Framework 6, следуя приведенным инструкциям here. Таким образом, у меня есть шаблонный метод, чтобы создать поддельные таблицы:Как я могу издеваться над методом возвращаемого макета?

protected Mock<DbSet<TheType>> MockDBSet<TheType>(List<TheType> data) where TheType : class 
    { 
     var mockSet = new Mock<DbSet<TheType>>(); 
     var dataSet = data.AsQueryable(); 
     mockSet.As<IQueryable<TheType>>().Setup(m => m.Provider).Returns(dataSet.Provider); 
     mockSet.As<IQueryable<TheType>>().Setup(m => m.Expression).Returns(dataSet.Expression); 
     mockSet.As<IQueryable<TheType>>().Setup(m => m.ElementType).Returns(dataSet.ElementType); 
     mockSet.As<IQueryable<TheType>>().Setup(m => m.GetEnumerator()).Returns(dataSet.GetEnumerator()); 
     mockSet.Setup(x => x.Add(It.IsAny<TheType>())) 
      .Returns(new Func<TheType, TheType>(x => 
      { 
       data.Add(x); 
       return data.Last(); 
      })); 

     return mockSet; 
    } 

Используя выше отлично работает для добавления и запрашивая фиктивную базу данных:

var db = new Mock<BloggingContext>(); 
db.Setup(m => m.Blog s).Returns(MockDBSet<Blog >(
    new List<Blog>() 
).Object); 

BloggingContext context = db.Object; 

Blog blog= new Blog(); 
context.Blogs.Add(blog); //fine 
Assert.IsTrue(context.Blogs.Count() == 1); //fine 

EF также обеспечивает «Local» собственности на предприятие коллекции, которые предоставляют доступ к не сохраненным объектам. Итак, когда не издевательски, BloggingContext.Blogs.Local передает обратно коллекцию ObservableCollection несохраненных объектов. Объекты перемещаются из BloggingContext.Blogs.Local в BloggingContext.Blogs, когда вызывается BloggingContext.SaveChanges().

Я хотел дразнить это поведение, так что я создал новый класс:

public class FakeBlogs : List<Blog> 
    { 
     ObservableCollection<Blog> _local = new ObservableCollection<Blog>(); 
     ObservableCollection<Blog> Local { get { return _local; } } 

     public void Add (Blog item) 
     { 
      _local.Add(item); 
     } 
    } 

Когда модульное тестирование, следующий код работает:

var db = new Mock<BloggingContext>(); 
db.Setup(m => m.Blog s).Returns(MockDBSet<Blog>(
    new FakeBlogs() //<===== Changed to use FakeBlogs 
).Object); 

BloggingContext context = db.Object; 

Blog blog= new Blog();  
context.Blogs.Add(blog); //fine 
Assert.IsTrue(context.Blogs.Count() == 1); //fine 

Однако, используя локальное свойство бросает NPE, поскольку локальное свойство имеет значение null.

var blog = (from i in context.Blogs.Local select i).FirstOrDefault();//throws NPE 

Как я могу издеваться над местным имуществом успешно?

+0

Добро пожаловать в StackOverflow! См. [«Если вопросы включают« теги »в их названиях?») (Http://meta.stackexchange.com/questions/19190/should-questions-include-tags-in-their-titles), где консенсус «нет, они не должны». –

+0

Спасибо за подсказку! – Shareef

+0

Действительно ли 'context.Blogs 'null, или это то, что вызывается при оценке выражения? Не могли бы вы предоставить stacktrace вашего исключения? – sisve

ответ

1

Исправлено. Я добавил следующую строку в функцию шаблона MockDBSet:

 mockSet.Setup(m => m.Local).Returns(data.Local); 

И объявил «Local» свойство FakeTable как общественность. Спасибо всем, кто проявил интерес.