2015-10-20 88 views
5

我需要爲每個單元測試都有一個登錄用戶,這迫使我在測試SetUp中執行異步調用(登錄)。c#中的異步單元測試安裝#

我無法找到一種方法來完成這項工作,我要麼得到空指針異常,要麼設置無效的簽名。

public async void SetUp() {} 

這使我的所有測試失敗,我的對象可能是因爲我沒有登錄。

public async Task SetUp() {} 

讓我所有的測試忽略,因爲設置有一個無效的簽名。

我想不必在每次測試中複製我的X系列設置,因爲它們都完全一樣,而且......這就是設置的目的。

我錯過了什麼?這看起來像一個微不足道的問題。

這裏是我現在,對顯示的東西

CreateTicketViewModel _viewModel; 

     [SetUp()] 
     public async void SetUp() //I have tried using Task instead of void 
     { 

      IUserService userService = Dependency.Instance.Resolve<IUserService>(); 
      await userService.LoginAsync(this.UserName, this.Password); 

      _viewModel = Dependency.Instance.Resolve<CreateTicketViewModel>(); 
     } 

     [TearDown()] 
     public void TearDown() 
     { 
      _viewModel = null; // I have tried removing this 
     } 

     [Test()] 
     public void Initialization() 
     { 
      // If I put what's in SetUp here and add "async" before void, 
      // it works just fine 

      Assert.IsNotNull(_viewModel); 
      Assert.IsNotNull(_viewModel.Ticket); 
     } 
+0

我已經閱讀了許多關於在SUT中沒有異步無效的博客文章,但我沒有,但這些博客文章都沒有談論自己的測試。 我有設計問題嗎? –

+0

難道你不能讓你的測試方法async而不是Setup方法嗎?或者你甚至可以使SetUp方法同步。前者雖然推薦。 –

+0

僅在其中聲明的異步測試顯示警告。如果可能,我希望避免這種情況。 –

回答

4

根據單元測試框架您使用async設置可能不被通過的框架正確處理。

在NUnits的情況下,我認爲它不支持異步設置方法。

,你應該在你的設置做那麼什麼是公正同步等待登錄完成:

userService.LoginAsync(this.UserName, this.Password).Wait();

編輯: 看起來它是一個開放的問題https://github.com/nunit/nunit/issues/60

這對MSTests的情況也是如此。

2

會不只是讓你的設置方法在所有不是異步和寫這個的緣故?

new Task(() => userService.LoginAsync(this.UserName, this.Password)).RunSynchronously() 
+0

當我這樣做時,我的userService的內容在測試開始時仍然爲空,因此失敗。 請注意,該LoginAsync方法後面有更多的異步調用。 –

+0

儘管我喜歡同步運行登錄的想法 –

2

不支持異步設置,但支持異步測試方法。您可以將測試方法設置爲異步而不是設置方法。

[TestFixture] 
public class AsyncSetupTest 
{ 
    private Task<CreateTicketViewModel> viewModelTask; 

    [SetUp()] 
    public void SetUp() 
    { 
     viewModelTask = Task.Run(async() => 
     { 
      IUserService userService = Dependency.Instance.Resolve<IUserService>(); 
      await userService.LoginAsync(this.UserName, this.Password); 

      return Dependency.Instance.Resolve<CreateTicketViewModel>(); 
     }); 
    } 

    [Test()] 
    public async Task Initialization() 
    { 
     CreateTicketViewModel viewModel = await viewModelTask; 

     Assert.IsNotNull(viewModel); 
     Assert.IsNotNull(viewModel.Ticket); 
    } 
} 

想法是,而不是讓所有Setup方法所做的設置工作,我們創建一個表示安裝完成並等待它在Test方法Task

這樣你就不會重複所有的設置邏輯。但只是從所有測試方法中提取Task的ViewModel。

+0

這會起作用,但仍然需要我在每次測試中都有一條重複行;但事實上它已經比我所做的更好。謝謝。另一方面,Dan Dinu的答案提供了一個「按原樣」的解決方案,只有在我的測試中有我的斷言,這意味着在我的設置中代碼更少,代碼塊更小。 –

+0

@Zil這將工作。但是,在異步代碼中阻塞從來不是一個好主意。 [你可能會陷入僵局](http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html)。 [也可以參考這個](http://blogs.msdn.com/b/pfxteam/archive/2011/01/13/10115163.aspx)。 –

+0

我同意產品代碼,但我確實希望我的測試在登錄過程中在此等待。你認爲在這種特定的情況下這樣做不好嗎?知道我沒有在這裏做任何其他的異步調用(而不是在登錄本身) –