2017-04-05 57 views
0

在一個ASPNET核心項目中,我試圖創建一些單元測試來驗證我的數據驗證邏輯是否正常工作。AspNetCore上的單元測試控制器模型驗證

我的控制器是非常簡單的:

[HttpPost] 
[Route("Track")] 
public void Track([FromBody] DataItem item) 
{ 
    if (!ModelState.IsValid) throw new ArgumentException("Bad request"); 

    _dataItemSaver.SaveData(item); 
} 

我使用的是測試的基類,將建立_myController對象作爲測試控制器。

public ControllerTestBase() 
    { 
     var builder = new ConfigurationBuilder() 
      .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) 
      .AddJsonFile($"buildversion.json", optional: true) 
      .AddEnvironmentVariables(); 
     _config = builder.Build(); 

     var services = new ServiceCollection() 
      .AddEntityFrameworkInMemoryDatabase() 
      .AddDbContext<MyDbContext>(options => 
      { 
       options.UseInMemoryDatabase(); 
      }) 
      .AddScoped<IDataItemSaver, DataItemSQLStorageService>() 
      .AddScoped<MyController>() 
      .Configure<MyConfig>(_config.GetSection(nameof(MyConfig))); 

     services 
      .AddMvc(mvcOptions => 
       { 
        mvcOptions.Filters.AddService(typeof(GlobalExceptionFilter), 0); 
       }); 

     _additionalDISetupActions?.Invoke(services); 

     _serviceProvider = services.BuildServiceProvider(); 

     _myController = _serviceProvider.GetService<MyController>(); 
    } 

測試也是非常簡單的:

[TestMethod] 
    public void Prop3Required() 
    { 
     // Arrange 
     var dataItem = new DataItem() 
     { 
      Prop1 = "Prop1", 
      Prop2 = "Prop2" 
     }; 

     // Act & Assert 
     Assert.ThrowsException<ArgumentException>(() => _myController.Track(dataItem)); 
    } 

我發現雖然這ModelState.IsValidtrue運行,即使我的DataItem缺少必需的屬性的單元測試(Prop3在這個例子中)時。當使用相同的輸入通過網絡測試控制器時,驗證工作是正確的(返回falseModelState.IsValid)。

如何從單元測試中正確觸發用於模型狀態驗證的ASPNET核心邏輯?

+1

你不是真的要拋出一個異常時,'ModelState'是無效的,你見https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/testing? –

+0

我做了,並在全局異常過濾器中處理異常,以保持所有錯誤處理和格式化在同一個地方。可以將支票移動到過濾器並全局應用,但會繼續拋出異常並將其處理到全局過濾器中。 –

+0

認真嗎?您的方法應該返回視圖,以便用戶可以更正驗證錯誤。 –

回答

4

您應該看看ASP.NET Core的集成測試(https://docs.microsoft.com/en-us/aspnet/core/testing/integration-testing),這是一種在測試環境中託管應用程序並測試整個管道的非常簡單的方法。
如文檔中解釋,你可以做這樣的事情在您的測試方法:

_server = new TestServer(new WebHostBuilder().UseStartup<Startup>()); 
_client = _server.CreateClient(); 
// Pass a not valid model 
var response = await _client.PostAsJsonAsync("Track", new DataItem()); 
Assert.IsFalse(response.IsSuccessStatusCode); 
+0

謝謝,這正是我一直在尋找的! –

1

如果你想要做的,你需要手動模擬模型狀態錯誤,因爲該模型狀態驗證只是一個純粹的單元測試在運行時觸發。

_myController.ModelState.AddModelError("yourItemFieldHere", "Your validation type here"); 

更多細節