2014-12-01 88 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 

我應該如何寫更新單元測試和刪除使用起訂量的行動?

+0

http://stackoverflow.com/questions/2295960/mocking-extension-methods-with-moq – dee 2014-12-01 16:36:20

+0

謝謝你,這是非常有用的鏈接。 – Vitone 2014-12-02 08:52:57

回答

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問題。 當我運行測試時,我得到一個excepton「模擬上的預期調用正好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)); 
    } 

這是我DeleteApplicationCommandHandler的Execute方法:

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測試方法失敗?