2013-04-26 50 views
2

好吧,我有一個奇怪的問題。測試不執行方法,除非我在方法的返回值上斷言

我在C#測試項目中使用NUnit和Moq。我認爲你可以忽略Mock對象,因爲真正的問題在於UserManager.AddUser()沒有正確執行。

以下代碼將永遠不會在UserManager.AddUser()的開始處達到斷點,並因此由於NullPointerException而導致Assertion失敗。

[Test] 
enter code here 
public void AddUser_NoPassword_GeneratesPassword() 
    { 
     //assert 
     var userRepositoryFake = new Mock<IUserRepository>(); 
     userRepositoryFake.Setup(x => x.GetUser(It.IsAny<string>(), It.IsAny<bool>())).Returns((User)null); 
     userRepositoryFake.Setup(x => x.SaveUser(It.IsAny<User>())).Returns(new Mock<User>().Object); 

     var userManager = new UserManager(userRepositoryStub.Object); 
     var createUserViewModel = new CreateUserViewModel { Username = "username" }; 

     //act 
     var validationErrors = userManager.AddUser(createUserViewModel); 

     //assert 
     Assert.IsNotNullOrEmpty(createUserViewModel.Password); 
    } 

不過,如果我添加了這一說法:

 //assert 
     Assert.IsEmpty(validationErrors); //new assertion 
     Assert.IsNotNullOrEmpty(createUserViewModel.Password); 

在ADDUSER斷點()到達,並測試成功。 看來測試不會執行AddUser(),除非它的返回值用於某些事情。

+1

您可以將代碼發佈到AddUser? – Pete 2013-04-26 15:11:41

+0

@ user1770699:AddUser的返回值是什麼?如果它是IEnumerable,它是否被枚舉? – 2013-04-26 15:12:02

回答

5

我的猜測是,AddUser是這樣實現的:

public IEnumerable<Error> AddUser(Model model) 
{ 
    // Do some stuff 
    if (foo) 
    { 
     yield return ...; 
    } 
    if (bar) 
    { 
     yield return ...; 
    } 
    // More stuff 
} 

換句話說,使用迭代器塊。迭代器塊是懶惰地執行的 - 代碼只在請求第一個元素時纔開始執行,即使這樣,當元素返回時它也會「暫停」。

鑑於這不是一個冪等查詢或類似的東西,我建議在內部實現使用List<Error>的方法會更有意義,您可以在內部添加並在最後返回。那樣的話,這個方法將會被執行,只是一次然而很多次迭代返回值。我懷疑這是預期的執行模式。

+0

非常感謝,我學到了一些有關收益回報的新知識。 – jorgenbs 2013-04-29 08:50:45