web-dev-qa-db-ja.com

単体テストでのモデルの状態の検証

私はこのようなコントローラーの単体テストを書いています:

public HttpResponseMessage PostLogin(LoginModel model)
{
    if (!ModelState.IsValid)
        return new HttpResponseMessage(HttpStatusCode.BadRequest);
}

モデルは次のようになります。

public class LoginModel
{
    [Required]
    public string Username { set; get; }
    [Required]
    public string Password { set; get; }
}

次に、次のような単体テストがあります。

[TestMethod]
public void TestLogin_InvalidModel()
{
    AccountController controller = CreateAccountController();

    ...
    var response = controller.PostLogin(new LoginModel() {  });

    Assert.AreEqual(HttpStatusCode.BadRequest, response.StatusCode);

}

実際、ModelStateは検証されています...両方のフィールドが必要なため、これは私には奇妙です...誰かがアドバイスできますか?

27
bandreas

モデルの状態が有効である理由は、コントローラーを新規作成すると新しいモデルの状態が作成されるためです。ここではWeb APIがパラメーターのバインドを行っていないため、モデルの状態エラーを追加する機会すらありません。

これを単体テストとして保持する場合は、自分でモデルの状態エラーを追加して、何が起こるかをテストする必要があります。

実際のリクエストでモデルの状態が無効になるかどうかをテストする場合は、次のブログ投稿を読むことをお勧めします。

http://blogs.msdn.com/b/youssefm/archive/2013/01/28/writing-tests-for-an-asp-net-webapi-service.aspx

インメモリサーバーに対してテストしてみてください。あなたのケースの1つのマイナーなメモは、リクエストでObjectContentではなくStringContentを使用して、Web APIがボディを非直列化して適切にバインドしようとすることを確認することです。

27

TL; DR Youssefが提供する記事全体を読みたくなく、ModelState.IsValidをfalseに戻す方法の簡単な解決策が必要な場合。これを行う。

[TestMethod]
public void TestLogin_InvalidModel()
{
    AccountController controller = CreateAccountController();
    // new code added -->
    controller.ModelState.AddModelError("fakeError", "fakeError");
    // end of new code
    ...
    var response = controller.PostLogin(new LoginModel() {  });

    Assert.AreEqual(HttpStatusCode.BadRequest, response.StatusCode);

}

これで、CreateAccountController()がこのように見えることを想像できます->

return new AccountApiController()
{
    Request = new HttpRequestMessage(),
    Configuration = new HttpConfiguration()
};

これがそれらのグーグルのための迅速な答えを与えることを願っています:)

20
Andreas

前述のように、ModelStateを検証するには統合テストが必要です。したがって、Asp.Net Coreを使用して、この質問を掘り下げて、テストをAsp.Net Coreと統合し、ModelStateを検証するための簡単なソリューションを追加します

パッケージを追加しますMicrosoft.AspNetCore.TestHostそして、このシンプルなリクエストを送信できます:

var server = new TestServer(new WebHostBuilder().UseStartup<Startup>());
var client = server.CreateClient();
var model = new { Name = String.Empty };
var content = new StringContent(JsonConvert.SerializeObject(model), Encoding.UTF8, "application/json");
var result = await client.PostAsync("/api/yourApiEndpoint", content);
result.StatusCode.Should().Be(HttpStatusCode.BadRequest);

詳細については、こちらをご覧ください: http://asp.net-hacker.rocks/2017/09/27/testing-aspnetcore.html

それが役に立てば幸い。

10
Bruno Avelar

以下を使用して、ユニットテストVisual Studio 2017、C#、NET 4.x.xでモデルの状態を検証しました

   [TestMethod]
        public void TestYourValidationModel()
        {
            var configuration = new HttpConfiguration();
            configuration.Filters.Add(new ValidateModelAttribute());
            // Get the quote
            var controller = new YourController
            {
                Request = new HttpRequestMessage(),
                Configuration = configuration
            };
            var request = YourRequestObject;
            controller.Request.Content = new ObjectContent<YourRequestType>(
                request, new JsonMediaTypeFormatter(), "application/json");
            controller.Validate(request);
            Assert.IsTrue(controller.ModelState.IsValid, "This must be valid");
        }

この例は、JSON形式のリクエストの場合です。コントローラの名前をYourControllerに置き換え、リクエストのオブジェクトタイプをYourRequesTypeに置き換えます。

これにより、サービスにアクセスせずにモデルの検証テストを行うことができます。

0
freedeveloper