2014-12-01 13 views
4

Я использую платформу Moq в своем модульном тесте. Это UpdateApplication метод испытания:Обновление, удаление методов модульного теста с использованием Moq

[TestMethod] 
public void UpdateApplication() 
{ 
    const string newAplpicationName = "NewApplication1"; 

    var data = 
     new[] 
     { 
      new Application { Id = 1, Name = "Application1" }, new Application { Id = 2, Name = "Application2" }, 
      new Application { Id = 3, Name = "Application3" }, new Application { Id = 4, Name = "Application4" } 
     } 
      .AsQueryable(); 

    var mockSet = new Mock<DbSet<Application>>(); 
    mockSet.As<IQueryable<Application>>().Setup(m => m.Provider).Returns(data.Provider); 
    mockSet.As<IQueryable<Application>>().Setup(m => m.Expression).Returns(data.Expression); 
    mockSet.As<IQueryable<Application>>().Setup(m => m.ElementType).Returns(data.ElementType); 
    mockSet.As<IQueryable<Application>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator()); 

    mockSet.Setup(m => m.AddOrUpdate(It.IsAny<Application[]>())).Callback(
     (Application[] apps) => 
     { 
      apps.FirstOrDefault(m => m.Id == 1).Name = newAplpicationName; 
     }).Verifiable(); // <-- Exception 

    var mockContext = new Mock<AppDbContext>(); 
    mockContext.Setup(c => c.Applications).Returns(mockSet.Object); 

    // Act 
    var commandHandler = new UpdateApplicationCommandHandler(mockContext.Object); 
    var commandArg = new ApplicationCommandArg { Id = 1, Name = newAplpicationName }; 
    commandHandler.Execute(new UpdateApplicationCommand(commandArg)); 

    // Verify 
    mockContext.Verify(m => m.SaveChanges(), Times.Once()); 
} 

Я получил исключение, когда запускали тест:

 
An exception of type 'System.NotSupportedException' occurred in Moq.dll but was 
not handled in user code 

Additional information: Expression references a method that does not belong to 
the mocked object: m => m.AddOrUpdate(It.IsAny()) 

    at Moq.Mock.ThrowIfNotMember(Expression setup, MethodInfo method) 
    at Moq.Mock.c__DisplayClass19`1.b__18() 
    at Moq.PexProtector.Invoke[T](Func`1 function) 
    at Moq.Mock.Setup[T](Mock`1 mock, Expression`1 expression, Condition condition) 
    at Moq.Mock`1.Setup(Expression`1 expression) 
    at UpdateApplication() in UpdateApplicationCommandTests.cs:line 39 

Как я должен писать тесты для обновления и удаления действия с помощью Moq?

+0

http://stackoverflow.com/questions/2295960/mocking-extension-methods-with-moq – dee

+0

Спасибо, это очень полезная ссылка. – Vitone

ответ

1

Проблема в том, что AddOrUpdate является методом расширения. Moq cannot mock extension methods, так что вам нужно будет найти другой способ достижения вашего охвата тестированием.

3

Этот вариант UpdateApplication метод модульного тестирования работает для меня, но я не уверен, что это правильно:

[TestMethod] 
    public void UpdateApplication() 
    { 
     const string newAplpicationName = "NewApplication1"; 

     var data = 
      new[] 
      { 
       new Application { Id = 1, Name = "Application1" }, new Application { Id = 2, Name = "Application2" }, 
       new Application { Id = 3, Name = "Application3" }, new Application { Id = 4, Name = "Application4" } 
      } 
       .AsQueryable(); 

     var mockSet = new Mock<DbSet<Application>>(); 
     mockSet.As<IQueryable<Application>>().Setup(m => m.Provider).Returns(data.Provider); 
     mockSet.As<IQueryable<Application>>().Setup(m => m.Expression).Returns(data.Expression); 
     mockSet.As<IQueryable<Application>>().Setup(m => m.ElementType).Returns(data.ElementType); 
     mockSet.As<IQueryable<Application>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator()); 

     var mockContext = new Mock<AppDbContext>(); 
     mockContext.Setup(m => m.Applications).Returns(mockSet.Object); 


     // Act 
     var commandHandler = new UpdateApplicationCommandHandler(mockContext.Object); 
     var commandArg = new ApplicationCommandArg { Id = 1, Name = newAplpicationName }; 
     commandHandler.Execute(new UpdateApplicationCommand(commandArg)); 

     Assert.AreEqual(newAplpicationName, data.First(m => m.Id == 1).Name); 

     mockContext.Verify(m => m.SaveChanges(), Times.Once()); 
    } 

Но я до сих пор есть проблемы с моей DeleteApplicationCommandTest. Когда я запускаю тест, я получаю исключение «Ожидаемое обращение к макету ровно 3 раза, но было 2 раза: m => m.Applications». Это метод испытания:

[TestMethod] 
    public void DeleteApplication() 
    { 
     var data = 
      new[] 
      { 
       new Application { Id = 1, Name = "Application1" }, new Application { Id = 2, Name = "Application2" }, 
       new Application { Id = 3, Name = "Application3" }, new Application { Id = 4, Name = "Application4" } 
      } 
       .AsQueryable(); 

     var mockSet = new Mock<DbSet<Application>>(); 
     mockSet.As<IQueryable<Application>>().Setup(m => m.Provider).Returns(data.Provider); 
     mockSet.As<IQueryable<Application>>().Setup(m => m.Expression).Returns(data.Expression); 
     mockSet.As<IQueryable<Application>>().Setup(m => m.ElementType).Returns(data.ElementType); 
     mockSet.As<IQueryable<Application>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator()); 

     var mockContext = new Mock<AppDbContext>(); 
     mockContext.Setup(m => m.Applications).Returns(mockSet.Object); 

     // Act 
     var commandHandler = new DeleteApplicationCommandHandler(mockContext.Object); 
     var commandArg = new ApplicationCommandArg { Id = 1 }; 
     commandHandler.Execute(new DeleteApplicationCommand(commandArg)); 

     // Verify 
     mockSet.Verify(m => m.Remove(It.IsAny<Application>()), Times.Once()); 
     mockContext.Verify(m => m.SaveChanges(), Times.Once()); 
     mockContext.VerifyGet(m => m.Applications, Times.Exactly(3)); 
    } 

Это мой метод Execute DeleteApplicationCommandHandler:

public override void Execute(DeleteApplicationCommand command) 
    { 
     Debug.WriteLine("DeleteApplicationCommand executed"); 

     var application = this.DbContext.Applications.FirstOrDefault(m => m.Id == command.CommandArg.Id); 

     if (application == null) 
     { 
      throw new Exception(string.Format("Application with id {0} was not found", command.CommandArg.Id)); 
     } 

     this.DbContext.Applications.Remove(application); 

     this.DbContext.SaveChanges(); 
    } 

Почему метод испытания DeleteApplication терпит неудачу?

Смежные вопросы