Search code examples
asp.netasp.net-web-apiodata

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


Solution

  • 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.