6

.NET Web Apiの使用経験はあまりありませんが、PluralsightでのJohn PapaのSPAアプリケーションチュートリアルに従って、しばらく使用しています。アプリケーションは正常に動作しますが、私が今苦労しているのは、POSTコントローラーの単体テストです。

私は、WebAPIコントローラーの単体テスト方法に関するこの素晴らしいガイドに従いました。私にとっての唯一の問題は、POSTメソッドのテストに関してです。

私のコントローラーは次のようになります。

    [ActionName("course")]
    public HttpResponseMessage Post(Course course)
    {
        if (course == null)
            throw new HttpResponseException(HttpStatusCode.NotAcceptable);
        try
        {
            Uow.Courses.Add(course);
            Uow.commit();
        }
        catch (Exception)
        {
            throw new HttpResponseException(HttpStatusCode.InternalServerError);
        }

        var response = Request.CreateResponse(HttpStatusCode.Created, course);

        string uri = Url.Link(routeName: "ControllerActionAndId", 
        routeValues: new { id = course.Id });

        response.Headers.Location = new Uri(uri);

        return response;
    }

そして、私の単体テストは次のようになります。

   [Test]
    public void PostShouldReturnHttpResponse()
    {
        var populatedPostController = new CoursesController(new TestUOW());

        SetupPostControllerForTest(populatedPostController);

        var course = new Course
        {
            Id = 12,
            Author = new UserProfile()
            {
                Firstname = "John",
                Lastname = "Johnson",
            },
            Description = "Testcourse",
            Title = "Test Title"
        };

          var responses = populatedPostController.Post(course);

          ObjectContent content = responses.Content as ObjectContent;
          Course result = (Course)content.Value;
          Assert.AreSame(result, course);
    }

ヘルプ機能付き:

    public static void SetupPostControllerForTest(ApiController controller)
    {

        var config = new HttpConfiguration();
        var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/api/courses/course");
        var route = config.Routes.MapHttpRoute(
            name: "ControllerActionAndId",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: null,
            constraints: new { id = @"^\d+$" }
        );

        var routeData = new HttpRouteData(route, new HttpRouteValueDictionary { { "controller", "courses" }, { "action", "course" } });

        controller.ControllerContext = new HttpControllerContext(config, routeData, request);
        controller.Request = request;
        controller.Request.Properties[HttpPropertyKeys.HttpConfigurationKey] = config;
    }

ユニットテストをデバッグすると、次の場所で失敗するようです。

        string uri = Url.Link(routeName: "ControllerActionAndId", 
        routeValues: new { id = course.Id });

        response.Headers.Location = new Uri(uri); //Exception because uri = null

Url.Linkがルートを見つけられないようです。

このガイドも試しましたが、上記の例を実際に機能させたいと思います。

ここで本当に基本的なものが欠けていますか?

4

1 に答える 1

5

はい、Nemesvが述べたように、構成に1行がありません。

controller.Request.Properties[HttpPropertyKeys.HttpRouteDataKey] = routeData

ご覧のとおり、UrlHelperを使用するためだけにコントローラーを構成することは非常に複雑です。そのため、コントローラークラスでのUrlHelperの使用を避ける傾向があります。私は通常、IUrlHelperのようにテストを簡単にするために外部依存関係を導入します。これにより、単体テストでの動作を模倣できます。

public interface IUrlHelper
    {
        string Link(string routeName, object routeValues);
        string Route(string routeName, object routeValues);
    }

    public class UrlHelperWrapper : IUrlHelper
    {
        UrlHelper helper;

        public UrlHelperWrapper(UrlHelper helper)
        {
            this.helper = helper;
        }

        public string Link(string routeName, object routeValues)
        {
            return this.helper.Link(routeName, routeValues);
        }

        public string Route(string routeName, object routeValues)
        {
            return this.helper.Route(routeName, routeValues);
        }
    }

このUrlHelperWraperを実際のWebAPIに挿入し、IUrlHelperインターフェイスのモックをテストに挿入します。そうすることで、ルートを使用した複雑な構成をすべて行う必要がなくなります。

よろしく、パブロ。

于 2013-03-14T14:04:09.420 に答える