Skip to content

Commit 13ee98a

Browse files
Chris Martinezcommonsensesoftware
Chris Martinez
authored andcommitted
Added initial OData API explorer tests
1 parent ba9ddcd commit 13ee98a

18 files changed

+590
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
namespace Microsoft.Web.Http.Description
2+
{
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Collections.ObjectModel;
6+
using System.Linq;
7+
using System.Web.Http.Dispatcher;
8+
9+
public class ControllerTypeCollection : Collection<Type>, IHttpControllerTypeResolver
10+
{
11+
public ControllerTypeCollection() { }
12+
13+
public ControllerTypeCollection( params Type[] controllerTypes ) : base( controllerTypes.ToList() ) { }
14+
15+
public ICollection<Type> GetControllerTypes( IAssembliesResolver assembliesResolver ) => this;
16+
}
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
namespace Microsoft.Web.Http.Description
2+
{
3+
using FluentAssertions;
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Linq;
7+
using System.Text;
8+
using System.Threading.Tasks;
9+
using System.Web.Http;
10+
using System.Web.OData;
11+
using Xunit;
12+
using static System.Net.Http.HttpMethod;
13+
14+
public class ODataApiExplorerTest
15+
{
16+
[Theory]
17+
[ClassData( typeof( TestConfigurations ) )]
18+
public void api_descriptions_should_collate_expected_versions( HttpConfiguration configuration )
19+
{
20+
// arrange
21+
var assembliesResolver = configuration.Services.GetAssembliesResolver();
22+
var controllerTypes = configuration.Services.GetHttpControllerTypeResolver().GetControllerTypes( assembliesResolver );
23+
var apiExplorer = new ODataApiExplorer( configuration );
24+
25+
// act
26+
var descriptions = apiExplorer.ApiDescriptions;
27+
28+
// assert
29+
descriptions.ApiVersions.Should().Equal(
30+
new ApiVersion( 0, 9 ),
31+
new ApiVersion( 1, 0 ),
32+
new ApiVersion( 2, 0 ),
33+
new ApiVersion( 3, 0 ) );
34+
}
35+
36+
[Theory]
37+
[ClassData( typeof( TestConfigurations ) )]
38+
public void api_descriptions_should_group_versioned_controllers( HttpConfiguration configuration )
39+
{
40+
// arrange
41+
var assembliesResolver = configuration.Services.GetAssembliesResolver();
42+
var controllerTypes = configuration.Services.GetHttpControllerTypeResolver().GetControllerTypes( assembliesResolver );
43+
var apiExplorer = new ODataApiExplorer( configuration );
44+
45+
// act
46+
var descriptions = apiExplorer.ApiDescriptions;
47+
48+
// assert
49+
descriptions.SelectMany( g => g.ApiDescriptions )
50+
.Select( d => d.ActionDescriptor.ControllerDescriptor.ControllerType )
51+
.Distinct()
52+
.Should()
53+
.Equal( controllerTypes );
54+
}
55+
56+
[Theory]
57+
[ClassData( typeof( TestConfigurations ) )]
58+
public void api_descriptions_should_flatten_versioned_controllers( HttpConfiguration configuration )
59+
{
60+
// arrange
61+
var assembliesResolver = configuration.Services.GetAssembliesResolver();
62+
var controllerTypes = configuration.Services.GetHttpControllerTypeResolver().GetControllerTypes( assembliesResolver );
63+
var apiExplorer = new ODataApiExplorer( configuration );
64+
65+
// act
66+
var descriptions = apiExplorer.ApiDescriptions;
67+
68+
// assert
69+
descriptions.Flatten()
70+
.Select( d => d.ActionDescriptor.ControllerDescriptor.ControllerType )
71+
.Distinct()
72+
.Should()
73+
.Equal( controllerTypes );
74+
}
75+
76+
[Theory]
77+
[ClassData( typeof( TestConfigurations ) )]
78+
public void api_descriptions_should_not_contain_metadata_controllers( HttpConfiguration configuration )
79+
{
80+
// arrange
81+
var assembliesResolver = configuration.Services.GetAssembliesResolver();
82+
var controllerTypes = configuration.Services.GetHttpControllerTypeResolver().GetControllerTypes( assembliesResolver );
83+
var apiExplorer = new ODataApiExplorer( configuration );
84+
85+
// act
86+
var descriptions = apiExplorer.ApiDescriptions;
87+
88+
// assert
89+
descriptions.Flatten()
90+
.Select( d => d.ActionDescriptor.ControllerDescriptor.ControllerType )
91+
.Distinct()
92+
.Should()
93+
.NotContain( type => typeof( MetadataController ).IsAssignableFrom( type ) );
94+
}
95+
96+
[Theory]
97+
[ClassData( typeof( TestConfigurations ) )]
98+
public void api_description_group_should_explore_v3_actions( HttpConfiguration configuration )
99+
{
100+
// arrange
101+
var apiVersion = new ApiVersion( 3, 0 );
102+
var apiExplorer = new ODataApiExplorer( configuration );
103+
var descriptionGroup = apiExplorer.ApiDescriptions[apiVersion];
104+
105+
// act
106+
var descriptions = descriptionGroup.ApiDescriptions;
107+
var relativePaths = descriptions.Select( d => d.RelativePath ).ToArray();
108+
109+
// assert
110+
descriptions.ShouldBeEquivalentTo(
111+
new[]
112+
{
113+
new
114+
{
115+
ID = $"GET{relativePaths[0]}",
116+
HttpMethod = Get,
117+
RelativePath = relativePaths[0],
118+
Version = apiVersion
119+
},
120+
new
121+
{
122+
ID = $"GET{relativePaths[1]}",
123+
HttpMethod = Get,
124+
RelativePath = relativePaths[1],
125+
Version = apiVersion
126+
},
127+
new
128+
{
129+
ID = $"POST{relativePaths[2]}",
130+
HttpMethod = Post,
131+
RelativePath = relativePaths[2],
132+
Version = apiVersion
133+
},
134+
new
135+
{
136+
ID = $"DELETE{relativePaths[3]}",
137+
HttpMethod = Delete,
138+
RelativePath = relativePaths[3],
139+
Version = apiVersion
140+
}
141+
},
142+
options => options.ExcludingMissingMembers() );
143+
}
144+
}
145+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
namespace Microsoft.Web.Http.Description
2+
{
3+
using Microsoft.Web.Http.Simulators.Configuration;
4+
using Microsoft.Web.Http.Simulators.Models;
5+
using Microsoft.Web.Http.Versioning.Conventions;
6+
using Microsoft.Web.OData.Builder;
7+
using System.Collections;
8+
using System.Collections.Generic;
9+
using System.Web.Http;
10+
using System.Web.Http.Dispatcher;
11+
12+
public class TestConfigurations : IEnumerable<object[]>
13+
{
14+
public IEnumerator<object[]> GetEnumerator()
15+
{
16+
yield return new object[] { NewOrdersConfiguration() };
17+
yield return new object[] { NewPeopleConfiguration() };
18+
}
19+
20+
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
21+
22+
public static HttpConfiguration NewOrdersConfiguration()
23+
{
24+
var configuration = new HttpConfiguration();
25+
var controllerTypeResolver = new ControllerTypeCollection(
26+
typeof( Simulators.V1.OrdersController ),
27+
typeof( Simulators.V2.OrdersController ),
28+
typeof( Simulators.V3.OrdersController ) );
29+
30+
configuration.Services.Replace( typeof( IHttpControllerTypeResolver ), controllerTypeResolver );
31+
configuration.AddApiVersioning(
32+
options =>
33+
{
34+
options.Conventions.Controller<Simulators.V1.OrdersController>()
35+
.HasApiVersion( 1, 0 )
36+
.HasDeprecatedApiVersion( 0, 9 )
37+
.Action( c => c.Post( default( Order ) ) ).MapToApiVersion( 1, 0 );
38+
options.Conventions.Controller<Simulators.V2.OrdersController>()
39+
.HasApiVersion( 2, 0 );
40+
options.Conventions.Controller<Simulators.V3.OrdersController>()
41+
.HasApiVersion( 3, 0 )
42+
.AdvertisesApiVersion( 4, 0 );
43+
} );
44+
var builder = new VersionedODataModelBuilder( configuration )
45+
{
46+
ModelConfigurations = { new OrderModelConfiguration() }
47+
};
48+
var models = builder.GetEdmModels();
49+
50+
configuration.MapVersionedODataRoutes( "odata", "api", models );
51+
52+
return configuration;
53+
}
54+
55+
public static HttpConfiguration NewPeopleConfiguration()
56+
{
57+
var configuration = new HttpConfiguration();
58+
var controllerTypeResolver = new ControllerTypeCollection(
59+
typeof( Simulators.V1.PeopleController ),
60+
typeof( Simulators.V2.PeopleController ),
61+
typeof( Simulators.V3.PeopleController ) );
62+
var builder = new VersionedODataModelBuilder( configuration )
63+
{
64+
ModelConfigurations = { new PersonModelConfiguration() }
65+
};
66+
var models = builder.GetEdmModels();
67+
68+
configuration.Services.Replace( typeof( IHttpControllerTypeResolver ), controllerTypeResolver );
69+
configuration.AddApiVersioning();
70+
configuration.MapVersionedODataRoutes( "odata", "api/v{apiVersion}", models );
71+
72+
return configuration;
73+
}
74+
}
75+
}

test/Microsoft.AspNet.OData.Versioning.ApiExplorer.Tests/Microsoft.AspNet.OData.Versioning.ApiExplorer.Tests.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
<ItemGroup>
2323
<Reference Include="System" />
24+
<Reference Include="System.ComponentModel.DataAnnotations" />
2425
<Reference Include="Microsoft.CSharp" />
2526
</ItemGroup>
2627

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
namespace Microsoft.Web.Http.Simulators.Configuration
2+
{
3+
using Microsoft.Web.Http;
4+
using Microsoft.Web.OData.Builder;
5+
using Models;
6+
using System.Web.OData.Builder;
7+
8+
public class OrderModelConfiguration : IModelConfiguration
9+
{
10+
public void Apply( ODataModelBuilder builder, ApiVersion apiVersion ) => builder.EntitySet<Order>( "Orders" );
11+
}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
namespace Microsoft.Web.Http.Simulators.Configuration
2+
{
3+
using Microsoft.Web.Http;
4+
using Microsoft.Web.OData.Builder;
5+
using Models;
6+
using System.Web.OData.Builder;
7+
8+
public class PersonModelConfiguration : IModelConfiguration
9+
{
10+
public void Apply( ODataModelBuilder builder, ApiVersion apiVersion ) => builder.EntitySet<Person>( "People" );
11+
}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace Microsoft.Web.Http.Simulators.Models
2+
{
3+
using System;
4+
using System.ComponentModel.DataAnnotations;
5+
6+
public class Order
7+
{
8+
[Key]
9+
public int Id { get; set; }
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace Microsoft.Web.Http.Simulators.Models
2+
{
3+
using System;
4+
using System.ComponentModel.DataAnnotations;
5+
6+
public class Person
7+
{
8+
[Key]
9+
public int Id { get; set; }
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
namespace Microsoft.Web.Http.Simulators.V1
2+
{
3+
using Microsoft.Web.Http.Description;
4+
using Microsoft.Web.Http.Simulators.Models;
5+
using System.Web.Http;
6+
using System.Web.Http.Description;
7+
using System.Web.OData;
8+
9+
public class OrdersController : ODataController
10+
{
11+
[ResponseType( typeof( ODataValue<Order> ) )]
12+
public IHttpActionResult Get( int id ) => Ok( new Order() { Id = id } );
13+
14+
[ResponseType( typeof( ODataValue<Order> ) )]
15+
public IHttpActionResult Post( [FromBody] Order order )
16+
{
17+
order.Id = 42;
18+
return Created( order );
19+
}
20+
}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
namespace Microsoft.Web.Http.Simulators.V1
2+
{
3+
using Microsoft.Web.Http;
4+
using Microsoft.Web.Http.Description;
5+
using Models;
6+
using System.Web.Http;
7+
using System.Web.Http.Description;
8+
using System.Web.OData;
9+
using System.Web.OData.Routing;
10+
11+
[ApiVersion( "0.9" )]
12+
[ApiVersion( "1.0" )]
13+
[ODataRoutePrefix( "People" )]
14+
public class PeopleController : ODataController
15+
{
16+
[HttpGet]
17+
[ODataRoute( "({id})" )]
18+
[ResponseType( typeof( ODataValue<Person> ) )]
19+
public IHttpActionResult Get( [FromODataUri] int id ) => Ok( new Person() { Id = id } );
20+
}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
namespace Microsoft.Web.Http.Simulators.V2
2+
{
3+
using Microsoft.Web.Http.Description;
4+
using Microsoft.Web.Http.Simulators.Models;
5+
using System.Collections.Generic;
6+
using System.Web.Http;
7+
using System.Web.Http.Description;
8+
using System.Web.OData;
9+
using static System.Linq.Enumerable;
10+
11+
public class OrdersController : ODataController
12+
{
13+
[ResponseType( typeof( ODataValue<IEnumerable<Order>> ) )]
14+
public IHttpActionResult Get() => Ok( Empty<Order>() );
15+
16+
[ResponseType( typeof( ODataValue<Order> ) )]
17+
public IHttpActionResult Get( int id ) => Ok( new Order() { Id = id } );
18+
19+
[ResponseType( typeof( ODataValue<Order> ) )]
20+
public IHttpActionResult Post( [FromBody] Order order )
21+
{
22+
order.Id = 42;
23+
return Created( order );
24+
}
25+
}
26+
}

0 commit comments

Comments
 (0)