Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can i unit test an EntitySetController

i try to unit test an EntitySetController. I can test Get but have problems in testing the Post Method.

I played around with SetODataPath and SetODataRouteName but when i call this.sut.Post(entity) i get a lot of errors regarding missing Location Header, missing OData-Path, missing Routes.

I am at my wit's end. Is there anybody out there who has successfully testet their EntitySetController?

Has anybody an idea for me? Maybe should i test only the protected overrided methods from my EntitySetController implementation? But how can i test protected methods?

Thanks for your help

like image 902
Andreas Richter Avatar asked Aug 01 '26 13:08

Andreas Richter


2 Answers

Came here looking for a solution aswell. This seems to work however not sure if there is a better way.

The controller needs a minimum of CreateEntity and GetKey overrides:

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

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

Where MyEntity is really simple:

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

Looks like you need at least: + Request with a URI + 3 keys in the request header, MS_HttpConfiguration, MS_ODataPath and MS_ODataRouteName + A HTTP configuration with a route

[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);
    }

I'm not too sure about the IHttpRoute, in the aspnet source code (I had to link to this to figure this all out) the tests use mocks of this interface. So for this test I just create a mock of this and implement the RouteTemplate property and GetVirtualPath method. All the others on the interface were not used during the test.

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      
}

This is working for me however I am really not too sure about the ODataPath and IHttpRoute and how to set it correctly.

like image 158
mynameisbob Avatar answered Aug 04 '26 02:08

mynameisbob


In addition to the answer from @mynameisbob, I have found you also may need to set the HttpRequestContext as well on the Request properties:

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

I needed the above additions for example when creating an HttpResponseMessage as follows:

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."
                }
            )
        );
    }

Without having the HttpRequestContext set, the above method will throw an Argument Null Exception as the CreateResponse extension method attempts to get the HttpConfiguration from the HttpRequestContext (rather than directly from the HttpRequest).

like image 45
mixja Avatar answered Aug 04 '26 04:08

mixja



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!