3

EntitySetController の単体テストを試みます。Get をテストできますが、Post メソッドのテストに問題があります。

SetODataPath と SetODataRouteName をいじってみましたが、this.sut.Post(entity) を呼び出すと、Location ヘッダーの欠落、OData-Path の欠落、Routes の欠落に関する多くのエラーが発生します。

私は途方に暮れています。EntitySetController のテストに成功した人はいますか?

誰か私にアイデアはありますか?EntitySetController 実装からの保護されたオーバーライドされたメソッドのみをテストする必要がありますか? しかし、保護されたメソッドをテストするにはどうすればよいですか?

ご協力いただきありがとうございます

4

5 に答える 5

5

解決策も探してここに来ました。これはうまくいくようですが、より良い方法があるかどうかはわかりません。

コントローラーには、少なくともCreateEntityGetKeyオーバーライドが必要です。

public class MyController : EntitySetController<MyEntity, int>
{
    protected override MyEntity CreateEntity(MyEntity entity)
    {
        return entity;
    }

    protected override int GetKey(MyEntity entity)
    {
        return entity.Id;
    }
}

MyEntity は本当に単純です。

public class MyEntity
{
    public int Id { get; set; }
    public string Name { get; set; }
}

+ URI を指定したリクエスト + リクエスト ヘッダー内の 3 つのキーMS_HttpConfiguration+ ルートを使用した HTTPMS_ODataPath構成MS_ODataRouteName

[TestMethod]
    public void CanPostToODataController()
    {
        var controller = new MyController();

        var config = new HttpConfiguration();
        var request = new HttpRequestMessage();

        config.Routes.Add("mynameisbob", new MockRoute());

        request.RequestUri = new Uri("http://www.thisisannoying.com/MyEntity");
        request.Properties.Add("MS_HttpConfiguration", config);
        request.Properties.Add("MS_ODataPath", new ODataPath(new EntitySetPathSegment("MyEntity")));
        request.Properties.Add("MS_ODataRouteName", "mynameisbob");

        controller.Request = request;

        var response = controller.Post(new MyEntity());

        Assert.IsNotNull(response);
        Assert.IsTrue(response.IsSuccessStatusCode);
        Assert.AreEqual(HttpStatusCode.Created, response.StatusCode);
    }

IHttpRouteaspnet ソース コード (これをすべて理解するためにこれにリンクする必要がありました)についてはよくわかりませんが、テストではこのインターフェイスのモックを使用します。したがって、このテストでは、これのモックを作成し、RouteTemplateプロパティとGetVirtualPathメソッドを実装するだけです。インターフェイス上の他のすべては、テスト中に使用されませんでした。

public class MockRoute : IHttpRoute
{
    public string RouteTemplate
    {
        get { return ""; }
    }

    public IHttpVirtualPathData GetVirtualPath(HttpRequestMessage request, IDictionary<string, object> values)
    {
        return new HttpVirtualPathData(this, "www.thisisannoying.com");
    }

    // implement the other methods but they are not needed for the test above      
}

これは私にとってはうまくいきますが、それを正しく設定する方法と方法ODataPathについてはよくわかりません。IHttpRoute

于 2013-06-05T14:53:01.967 に答える
1

@mynameisbob からの回答に加えて、Request プロパティで HttpRequestContext も設定する必要がある場合があることがわかりました。

var requestContext = new HttpRequestContext();
requestContext.Configuration = config;
request.Properties.Add(HttpPropertyKeys.RequestContextKey, requestContext);

たとえば、次のように HttpResponseMessage を作成するときに、上記の追加が必要でした。

public virtual HttpResponseException NotFound(HttpRequestMessage request)
    {
        return new HttpResponseException(
            request.CreateResponse(
                HttpStatusCode.NotFound,
                new ODataError
                {
                    Message = "The entity was not found.",
                    MessageLanguage = "en-US",
                    ErrorCode = "Entity Not Found."
                }
            )
        );
    }

HttpRequestContext を設定しないと、CreateResponse 拡張メソッドが (HttpRequest から直接ではなく) HttpRequestContext から HttpConfiguration を取得しようとするため、上記のメソッドは Argument Null Exception をスローします。

于 2013-09-14T04:21:39.103 に答える
1

OK更新された回答。

返された IHttpActionResult の実行を正常にサポートすることもわかりました。さらにいくつかのことが必要です。

これが私がこれまでに見つけた最良のアプローチです。より良い方法があると確信していますが、これは私にとってはうまくいきます:

// Register OData configuration with HTTP Configuration object
// Create an ODataConfig or similar class in App_Start 
ODataConfig.Register(config);

// Get OData Parameters - suggest exposing a public GetEdmModel in ODataConfig
IEdmModel model = ODataConfig.GetEdmModel();
IEdmEntitySet edmEntitySet = model.EntityContainers().Single().FindEntitySet("Orders"); 
ODataPath path = new ODataPath(new EntitySetPathSegment(edmEntitySet));

// OData Routing Convention Configuration
var routingConventions = ODataRoutingConventions.CreateDefault();

// Attach HTTP configuration to HttpRequestContext
requestContext.Configuration = config;

// Attach Request URI
request.RequestUri = requestUri;

// Attach Request Properties
request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, config);
request.Properties.Add(HttpPropertyKeys.RequestContextKey, requestContext);
request.Properties.Add("MS_ODataPath", path);
request.Properties.Add("MS_ODataRouteName", "ODataRoute");
request.Properties.Add("MS_EdmModel", model);
request.Properties.Add("MS_ODataRoutingConventions", routingConventions);
request.Properties.Add("MS_ODataPathHandler", new DefaultODataPathHandler());
于 2013-09-19T05:50:03.577 に答える
0

また、正しい Location ヘッダー値などを取得するには、Web API アプリケーションの OData 構成コードを呼び出す必要があります。

したがって、使用するのではなく:

config.Routes.Add("mynameisbob", new MockRoute());

OData ルートを設定する WebApiConfig クラスの部分を別のクラス (ODataConfig など) に分離し、それを使用してテスト用の正しいルートを登録する必要があります。

例えば

ODataConfig.Register(config);

次に注意する必要があるのは、次の行がルーティング構成と一致することだけです。

request.Properties.Add("MS_ODataPath", new ODataPath(new EntitySetPathSegment("MyEntity")));
request.Properties.Add("MS_ODataRouteName", "mynameisbob");

したがって、Web API OData 構成が次のようになっているとします。

    config.Routes.MapODataRoute("ODataRoute", "odata", GetEdmModel());

    private static IEdmModel GetEdmModel()
        {
            ODataModelBuilder modelBuilder = new ODataConventionModelBuilder();
            modelBuilder.EntitySet<MyEntity>("MyEntities");
            IEdmModel model = modelBuilder.GetEdmModel();
            return model;
        }

次に、これが正しい構成です。

request.Properties.Add("MS_ODataPath", new ODataPath(new EntitySetPathSegment("MyEntities")));
request.Properties.Add("MS_ODataRouteName", "ODataRoute");

これにより、Location ヘッダーが正しく生成されます。

于 2013-09-14T06:08:44.767 に答える