Esempio n. 1
0
        public void CanCreateActionWithComplexReturnType()
        {
            // Arrange
            // Act
            ODataModelBuilder builder = new ODataModelBuilder();

            ActionConfiguration createAddress   = builder.Action("CreateAddress").Returns <Address>();
            ActionConfiguration createAddresses = builder.Action("CreateAddresses").ReturnsCollection <Address>();

            // Assert
            ComplexTypeConfiguration address = createAddress.ReturnType as ComplexTypeConfiguration;

            Assert.NotNull(address);
            Assert.Equal(typeof(Address).FullName, address.FullName);
            Assert.Null(createAddress.NavigationSource);

            CollectionTypeConfiguration addresses = createAddresses.ReturnType as CollectionTypeConfiguration;

            Assert.NotNull(addresses);
            Assert.Equal(string.Format("Collection({0})", typeof(Address).FullName), addresses.FullName);
            address = addresses.ElementType as ComplexTypeConfiguration;
            Assert.NotNull(address);
            Assert.Equal(typeof(Address).FullName, address.FullName);
            Assert.Null(createAddresses.NavigationSource);
        }
        public void CanCreateActionWithNoArguments()
        {
            // Arrange
            // Act
            ODataModelBuilder builder = new ODataModelBuilder();

            builder.Namespace     = "MyNamespace";
            builder.ContainerName = "MyContainer";
            ActionConfiguration action   = builder.Action("Format");
            ActionConfiguration actionII = builder.Action("FormatII");

            actionII.Namespace = "MyNamespaceII";

            // Assert
            Assert.Equal("Format", action.Name);
            Assert.Equal(OperationKind.Action, action.Kind);
            Assert.NotNull(action.Parameters);
            Assert.Empty(action.Parameters);
            Assert.Null(action.ReturnType);
            Assert.True(action.IsSideEffecting);
            Assert.False(action.IsComposable);
            Assert.False(action.IsBindable);
            Assert.Equal("MyNamespace", action.Namespace);
            Assert.Equal("MyNamespace.Format", action.FullyQualifiedName);
            Assert.Equal("MyNamespaceII", actionII.Namespace);
            Assert.Equal("MyNamespaceII.FormatII", actionII.FullyQualifiedName);
            Assert.NotNull(builder.Operations);
            Assert.Equal(2, builder.Operations.Count());
        }
Esempio n. 3
0
        public void CanCreateActionWithEntityReturnType()
        {
            // Arrange
            // Act
            ODataModelBuilder builder = new ODataModelBuilder();

            ActionConfiguration createGoodCustomer = builder.Action("CreateGoodCustomer").ReturnsFromEntitySet <Customer>("GoodCustomers");
            ActionConfiguration createBadCustomers = builder.Action("CreateBadCustomers").ReturnsCollectionFromEntitySet <Customer>("BadCustomers");

            // Assert
            EntityTypeConfiguration customer = createGoodCustomer.ReturnType as EntityTypeConfiguration;

            Assert.NotNull(customer);
            Assert.Equal(typeof(Customer).FullName, customer.FullName);
            EntitySetConfiguration goodCustomers = builder.EntitySets.SingleOrDefault(s => s.Name == "GoodCustomers");

            Assert.NotNull(goodCustomers);
            Assert.Same(createGoodCustomer.NavigationSource, goodCustomers);

            CollectionTypeConfiguration customers = createBadCustomers.ReturnType as CollectionTypeConfiguration;

            Assert.NotNull(customers);
            customer = customers.ElementType as EntityTypeConfiguration;
            Assert.NotNull(customer);
            EntitySetConfiguration badCustomers = builder.EntitySets.SingleOrDefault(s => s.Name == "BadCustomers");

            Assert.NotNull(badCustomers);
            Assert.Same(createBadCustomers.NavigationSource, badCustomers);
        }
Esempio n. 4
0
        public void GetEdmModel_ThrowsException_WhenUnboundActionOverloaded()
        {
            // Arrange
            ODataModelBuilder builder = new ODataModelBuilder();

            builder.Action("ActionName").Parameter <int>("Param1");
            builder.Action("ActionName").Returns <string>();

            // Act & Assert
            Assert.Throws <InvalidOperationException>(() => builder.GetEdmModel(),
                                                      "Found more than one unbound action with name 'ActionName'. " +
                                                      "Each unbound action must have an unique action name.");
        }
        public void RemoveOperationByNameThrowsWhenAmbiguous()
        {
            // Arrange
            // Act
            ODataModelBuilder builder = new ODataModelBuilder();

            ActionConfiguration action1 = builder.Action("Format");
            ActionConfiguration action2 = builder.Action("Format");

            action2.Parameter <int>("SegmentSize");

            Assert.Throws <InvalidOperationException>(() =>
            {
                builder.RemoveOperation("Format");
            });
        }
Esempio n. 6
0
        public void CanCreateActionWithNonbindingParameters()
        {
            // Arrange
            // Act
            ODataModelBuilder   builder = new ODataModelBuilder();
            ActionConfiguration action  = builder.Action("MyAction");

            action.Parameter <string>("p0");
            action.Parameter <int>("p1");
            action.Parameter <Address>("p2");
            action.CollectionParameter <string>("p3");
            action.CollectionParameter <int>("p4");
            action.CollectionParameter <ZipCode>("p5");
            ParameterConfiguration[]   parameters   = action.Parameters.ToArray();
            ComplexTypeConfiguration[] complexTypes = builder.StructuralTypes.OfType <ComplexTypeConfiguration>().ToArray();

            // Assert
            Assert.Equal(2, complexTypes.Length);
            Assert.Equal(typeof(Address).FullName, complexTypes[0].FullName);
            Assert.Equal(typeof(ZipCode).FullName, complexTypes[1].FullName);
            Assert.Equal(6, parameters.Length);
            Assert.Equal("p0", parameters[0].Name);
            Assert.Equal("Edm.String", parameters[0].TypeConfiguration.FullName);
            Assert.Equal("p1", parameters[1].Name);
            Assert.Equal("Edm.Int32", parameters[1].TypeConfiguration.FullName);
            Assert.Equal("p2", parameters[2].Name);
            Assert.Equal(typeof(Address).FullName, parameters[2].TypeConfiguration.FullName);
            Assert.Equal("p3", parameters[3].Name);
            Assert.Equal("Collection(Edm.String)", parameters[3].TypeConfiguration.FullName);
            Assert.Equal("p4", parameters[4].Name);
            Assert.Equal("Collection(Edm.Int32)", parameters[4].TypeConfiguration.FullName);
            Assert.Equal("p5", parameters[5].Name);
            Assert.Equal(string.Format("Collection({0})", typeof(ZipCode).FullName), parameters[5].TypeConfiguration.FullName);
        }
Esempio n. 7
0
        public void CanCreateEdmModel_WithNonBindableAction()
        {
            // Arrange
            ODataModelBuilder builder = ODataModelBuilderMocks.GetModelBuilderMock <ODataModelBuilder>();

            // Act
            ActionConfiguration actionConfiguration = builder.Action("ActionName");

            actionConfiguration.ReturnsFromEntitySet <Customer>("Customers");

            IEdmModel model = builder.GetEdmModel();

            // Assert
            IEdmEntityContainer container = model.EntityContainer;

            Assert.NotNull(container);
            Assert.Equal(1, container.Elements.OfType <IEdmActionImport>().Count());
            Assert.Equal(1, container.Elements.OfType <IEdmEntitySet>().Count());
            IEdmActionImport action = container.Elements.OfType <IEdmActionImport>().Single();

            Assert.False(action.Action.IsBound);
            Assert.Equal("ActionName", action.Name);
            Assert.NotNull(action.Action.ReturnType);
            Assert.NotNull(action.EntitySet);
            Assert.Equal("Customers", (action.EntitySet as IEdmEntitySetReferenceExpression).ReferencedEntitySet.Name);
            Assert.Equal(
                typeof(Customer).FullName,
                (action.EntitySet as IEdmEntitySetReferenceExpression).ReferencedEntitySet.EntityType().FullName());
            Assert.Empty(action.Action.Parameters);
        }
Esempio n. 8
0
        public void CanCreateFunctionWithNoArguments()
        {
            // Arrange
            // Act
            ODataModelBuilder builder = new ODataModelBuilder();

            builder.Namespace     = "MyNamespace";
            builder.ContainerName = "MyContainer";
            FunctionConfiguration function   = builder.Function("Format");
            ActionConfiguration   functionII = builder.Action("FormatII");

            functionII.Namespace = "MyNamespaceII";

            // Assert
            Assert.Equal("Format", function.Name);
            Assert.Equal(ProcedureKind.Function, function.Kind);
            Assert.NotNull(function.Parameters);
            Assert.Empty(function.Parameters);
            Assert.Null(function.ReturnType);
            Assert.False(function.IsSideEffecting);
            Assert.False(function.IsComposable);
            Assert.False(function.IsBindable);
            Assert.False(function.SupportedInFilter);
            Assert.False(function.SupportedInOrderBy);
            Assert.Equal("MyNamespace", function.Namespace);
            Assert.Equal("MyNamespace.Format", function.FullyQualifiedName);
            Assert.Equal("MyNamespaceII", functionII.Namespace);
            Assert.Equal("MyNamespaceII.FormatII", functionII.FullyQualifiedName);
            Assert.NotNull(builder.Procedures);
            Assert.Equal(2, builder.Procedures.Count());
        }
        public void CanCreateActionWithReturnTypeAsNullableByDefault()
        {
            // Arrange & Act
            ODataModelBuilder   builder = new ODataModelBuilder();
            ActionConfiguration action  = builder.Action("MyAction").Returns <Address>();

            // Assert
            Assert.True(action.OptionalReturn);
        }
Esempio n. 10
0
        public void ReturnsCollectionFromEntitySet_ThrowsArgumentNull_EntitySetConfiguration()
        {
            // Arrange
            ODataModelBuilder builder = new ODataModelBuilder();
            var action = builder.Action("action");

            // Act & Assert
            Assert.ThrowsArgumentNull(() => action.ReturnsCollectionFromEntitySet <Movie>(entitySetConfiguration: null),
                                      "entitySetConfiguration");
        }
Esempio n. 11
0
        public void CanRemoveOperationByName()
        {
            // Arrange
            // Act
            ODataModelBuilder   builder = new ODataModelBuilder();
            ActionConfiguration action  = builder.Action("Format");
            bool removed = builder.RemoveOperation("Format");

            // Assert
            Assert.Equal(0, builder.Operations.Count());
        }
        public void HasFeedActionLink_ThrowsException_OnNonBindableActions()
        {
            // Arrange
            ODataModelBuilder   builder = new ODataModelBuilder();
            ActionConfiguration action  = builder.Action("NoBindableAction");

            // Act & Assert
            Assert.Throws <InvalidOperationException>(
                () => action.HasFeedActionLink(ctx => new Uri("http://any"), followsConventions: false),
                "To register an action link factory, actions must be bindable to the collection of entity. " +
                "Action 'NoBindableAction' does not meet this requirement.");
        }
Esempio n. 13
0
        public void CanRemoveProcedure()
        {
            // Arrange
            // Act
            ODataModelBuilder      builder   = new ODataModelBuilder();
            ActionConfiguration    action    = builder.Action("Format");
            ProcedureConfiguration procedure = builder.Procedures.SingleOrDefault();
            bool removed = builder.RemoveProcedure(procedure);

            // Assert
            Assert.True(removed);
            Assert.Equal(0, builder.Procedures.Count());
        }
Esempio n. 14
0
        public void ReturnsCollection_ThrowsInvalidOperationException_IfReturnTypeIsEntity()
        {
            // Arrange
            ODataModelBuilder builder = new ODataModelBuilder();

            builder.EntityType <Movie>();
            var action = builder.Action("action");

            // Act & Assert
            Assert.Throws <InvalidOperationException>(() => action.ReturnsCollection <Movie>(),
                                                      "The EDM type 'System.Web.OData.Builder.Movie' is already declared as an entity type. Use the " +
                                                      "method 'ReturnsCollectionFromEntitySet' if the return type is an entity collection.");
        }
Esempio n. 15
0
        public void CanRemoveOperation()
        {
            // Arrange
            // Act
            ODataModelBuilder      builder   = new ODataModelBuilder();
            ActionConfiguration    action    = builder.Action("Format");
            OperationConfiguration operation = builder.Operations.SingleOrDefault();
            bool removed = builder.RemoveOperation(operation);

            // Assert
            Assert.True(removed);
            Assert.Equal(0, builder.Operations.Count());
        }
Esempio n. 16
0
        public void CanCreateActionWithPrimitiveCollectionReturnType()
        {
            // Arrange
            // Act
            ODataModelBuilder   builder = new ODataModelBuilder();
            ActionConfiguration action  = builder.Action("CreateMessages");

            action.ReturnsCollection <string>();

            // Assert
            Assert.NotNull(action.ReturnType);
            Assert.Equal("Collection(Edm.String)", action.ReturnType.FullName);
        }
Esempio n. 17
0
        public void Returns_ThrowsInvalidOperationIfGenericArgumentIsDateTime(Type type)
        {
            // Arrange
            ODataModelBuilder   builder = new ODataModelBuilder();
            ActionConfiguration action  = builder.Action("Format");
            MethodInfo          method  = typeof(ActionConfiguration)
                                          .GetMethod("Returns")
                                          .MakeGenericMethod(type);

            // Act & Assert
            Assert.Throws <InvalidOperationException>(
                () => method.Invoke(action, new object[] { }),
                string.Format("The type '{0}' is not a supported return type.", type.FullName));
        }
Esempio n. 18
0
        public void Parameter_ThrowsInvalidOperationIfGenericArgumentIsDateTime(Type type)
        {
            // Arrange
            ODataModelBuilder   builder = new ODataModelBuilder();
            ActionConfiguration action  = builder.Action("Format");
            MethodInfo          method  = typeof(ActionConfiguration)
                                          .GetMethod("Parameter", new[] { typeof(string) })
                                          .MakeGenericMethod(type);

            // Act & Assert
            Assert.Throws <InvalidOperationException>(
                () => method.Invoke(action, new[] { "test" }),
                string.Format("The type '{0}' is not a supported parameter type for the parameter test.", type.FullName));
        }
Esempio n. 19
0
        public void GetEdmModel_CreatesOperationImports_For_UnboundedOperations()
        {
            // Arrange
            ODataModelBuilder builder = new ODataModelBuilder();

            builder.Function("Function").Returns <bool>();
            builder.Action("Action").Returns <bool>();

            // Act
            IEdmModel model = builder.GetEdmModel();

            // Assert
            Assert.Equal(2, model.EntityContainer.OperationImports().Count());
        }
Esempio n. 20
0
        public void ReturnsCollectionFromEntitySet_Sets_EntitySetAndReturnType()
        {
            // Arrange
            string            entitySetName = "movies";
            ODataModelBuilder builder       = new ODataModelBuilder();
            var movies = builder.EntitySet <Movie>(entitySetName);
            var action = builder.Action("Action");

            // Act
            action.ReturnsCollectionFromEntitySet(movies);

            // Assert
            Assert.Equal(entitySetName, action.NavigationSource.Name);
            Assert.Equal(typeof(IEnumerable <Movie>), action.ReturnType.ClrType);
        }
Esempio n. 21
0
        public void AttemptToRemoveNonExistantEntityReturnsFalse()
        {
            // Arrange
            ODataModelBuilder      builder  = new ODataModelBuilder();
            ODataModelBuilder      builder2 = new ODataModelBuilder();
            ProcedureConfiguration toRemove = builder2.Action("ToRemove");

            // Act
            bool removedByName = builder.RemoveProcedure("ToRemove");
            bool removed       = builder.RemoveProcedure(toRemove);

            //Assert
            Assert.False(removedByName);
            Assert.False(removed);
        }
Esempio n. 22
0
        public void Cant_SetActionTile_OnNonBindableActions()
        {
            // Arrange
            ODataModelBuilder   builder = new ODataModelBuilder();
            ActionConfiguration action  = builder.Action("MyAction");

            action.Returns <int>();
            action.Title = "My Action";

            // Act
            IEdmModel           model        = builder.GetEdmModel();
            IEdmOperationImport actionImport = model.EntityContainer.OperationImports().OfType <IEdmActionImport>().Single();

            Assert.NotNull(actionImport);
            OperationTitleAnnotation actionTitleAnnotation = model.GetOperationTitleAnnotation(actionImport.Operation);

            // Assert
            Assert.Null(actionTitleAnnotation);
        }
        public void CanCreateActionWithNonbindingParametersAsNullable()
        {
            // Arrange & Act
            ODataModelBuilder   builder = new ODataModelBuilder();
            ActionConfiguration action  = builder.Action("MyAction");

            action.Parameter <string>("p0");
            action.Parameter <string>("p1").OptionalParameter = false;
            action.Parameter <int>("p2").OptionalParameter    = true;
            action.Parameter <int>("p3");
            action.Parameter <Address>("p4");
            action.Parameter <Address>("p5").OptionalParameter = false;

            action.CollectionParameter <ZipCode>("p6");
            action.CollectionParameter <ZipCode>("p7").OptionalParameter = false;

            action.EntityParameter <Customer>("p8");
            action.EntityParameter <Customer>("p9").OptionalParameter = false;

            action.CollectionEntityParameter <Customer>("p10");
            action.CollectionEntityParameter <Customer>("p11").OptionalParameter = false;
            Dictionary <string, ParameterConfiguration> parameters = action.Parameters.ToDictionary(e => e.Name, e => e);

            // Assert
            Assert.True(parameters["p0"].OptionalParameter);
            Assert.False(parameters["p1"].OptionalParameter);

            Assert.True(parameters["p2"].OptionalParameter);
            Assert.False(parameters["p3"].OptionalParameter);

            Assert.True(parameters["p4"].OptionalParameter);
            Assert.False(parameters["p5"].OptionalParameter);

            Assert.True(parameters["p6"].OptionalParameter);
            Assert.False(parameters["p7"].OptionalParameter);

            Assert.True(parameters["p8"].OptionalParameter);
            Assert.False(parameters["p9"].OptionalParameter);

            Assert.True(parameters["p10"].OptionalParameter);
            Assert.False(parameters["p11"].OptionalParameter);
        }
        public void CanCreateActionWithNonbindingParameters_AddParameterNonGenericMethod()
        {
            // Arrange
            // Act
            ODataModelBuilder   builder = new ODataModelBuilder();
            ActionConfiguration action  = builder.Action("MyAction");

            action.Parameter(typeof(string), "p0");
            action.Parameter(typeof(int), "p1");
            action.Parameter(typeof(Address), "p2");
            ParameterConfiguration[] parameters = action.Parameters.ToArray();

            // Assert
            Assert.Equal(3, parameters.Length);
            Assert.Equal("p0", parameters[0].Name);
            Assert.Equal("Edm.String", parameters[0].TypeConfiguration.FullName);
            Assert.Equal("p1", parameters[1].Name);
            Assert.Equal("Edm.Int32", parameters[1].TypeConfiguration.FullName);
            Assert.Equal("p2", parameters[2].Name);
            Assert.Equal(typeof(Address).FullName, parameters[2].TypeConfiguration.FullName);
        }
Esempio n. 25
0
        public void UnboundAction_ForEnumTypeInODataModelBuilder()
        {
            // Arrange
            ODataModelBuilder   builder             = new ODataModelBuilder().Add_Color_EnumType();
            ActionConfiguration actionConfiguration = builder.Action("UnboundAction");

            actionConfiguration.Parameter <Color>("Color");
            actionConfiguration.Returns <Color>();

            // Act & Assert
            IEdmModel        model        = builder.GetEdmModel();
            IEdmActionImport actionImport = model.EntityContainer.OperationImports().Single(o => o.Name == "UnboundAction") as IEdmActionImport;

            IEdmTypeReference color      = actionImport.Action.Parameters.Single(p => p.Name == "Color").Type;
            IEdmTypeReference returnType = actionImport.Action.ReturnType;
            IEdmEnumType      colorType  = model.SchemaElements.OfType <IEdmEnumType>().Single(e => e.Name == "Color");

            Assert.False(color.IsNullable);
            Assert.Same(colorType, color.Definition);
            Assert.False(returnType.IsNullable);
            Assert.Same(colorType, returnType.Definition);
        }
Esempio n. 26
0
        public void CanBuildOperationBoundToCollectionCacheForIEdmModel()
        {
            // Arrange
            ODataModelBuilder builder = new ODataModelBuilder();
            EntityTypeConfiguration <Customer> customer = builder.EntitySet <Customer>("Customers").EntityType;

            customer.HasKey(c => c.ID);
            customer.Property(c => c.Name);
            customer.ComplexProperty(c => c.Address);

            EntityTypeConfiguration <Movie> movie = builder.EntitySet <Movie>("Movies").EntityType;

            movie.HasKey(m => m.ID);
            movie.HasKey(m => m.Name);
            EntityTypeConfiguration <Blockbuster> blockBuster = builder.EntityType <Blockbuster>().DerivesFrom <Movie>();
            EntityTypeConfiguration movieConfiguration        = builder.StructuralTypes.OfType <EntityTypeConfiguration>().Single(t => t.Name == "Movie");

            // build actions that are bindable to the collection of entity
            customer.Collection.Action("CollectionCustomerActionInCache1");
            customer.Collection.Action("CollectionCustomerActionInCache2");
            movie.Collection.Action("CollectionMovieActionInCache3");

            ActionConfiguration         movieActionIncache4     = builder.Action("CollectionMovieActionInCache4");
            CollectionTypeConfiguration collectionConfiguration = new CollectionTypeConfiguration(movieConfiguration, typeof(Movie));

            movieActionIncache4.SetBindingParameter("bindingParameter", collectionConfiguration);

            blockBuster.Collection.Action("CollectionBlockbusterActionInCache5");

            // build functions that are bindable to the collection of entity
            customer.Collection.Function("CollectionCustomerFunctionInCache1").Returns <int>();
            customer.Collection.Function("CollectionCustomerFunctionInCache2").Returns <int>();
            movie.Collection.Function("CollectionMovieFunctionInCache3").Returns <int>();
            blockBuster.Collection.Function("CollectionBlockbusterFunctionInCache5").Returns <int>();

            // build actions that are either: bindable to an entity, have no parameter, have only complex parameter
            customer.Action("CustomersActionNotInCache1");
            customer.Function("CustomersFunctionNotInCache1").Returns <int>();
            movie.Action("MoviesActionNotInCache2");
            builder.Action("NoParametersNotInCache3");

            ActionConfiguration addressParameterNotInCache4 = builder.Action("AddressParameterNotInCache4");

            addressParameterNotInCache4.Parameter <Address>("address");

            IEdmModel model = builder.GetEdmModel();

            IEdmEntityType customerType    = model.SchemaElements.OfType <IEdmEntityType>().Single(e => e.Name == "Customer");
            IEdmEntityType movieType       = model.SchemaElements.OfType <IEdmEntityType>().Single(e => e.Name == "Movie");
            IEdmEntityType blockBusterType = model.SchemaElements.OfType <IEdmEntityType>().Single(e => e.Name == "Blockbuster");

            // Act
            BindableOperationFinder annotation = new BindableOperationFinder(model);
            var movieOperations       = annotation.FindOperationsBoundToCollection(movieType).ToArray();
            var customerOperations    = annotation.FindOperationsBoundToCollection(customerType).ToArray();
            var blockBusterOperations = annotation.FindOperationsBoundToCollection(blockBusterType).ToArray();

            // Assert
            Assert.Equal(3, movieOperations.Length);
            Assert.Single(movieOperations.Where(a => a.Name == "CollectionMovieActionInCache3"));
            Assert.Single(movieOperations.Where(a => a.Name == "CollectionMovieActionInCache4"));
            Assert.Single(movieOperations.Where(a => a.Name == "CollectionMovieFunctionInCache3"));

            Assert.Equal(4, customerOperations.Length);
            Assert.Single(customerOperations.Where(a => a.Name == "CollectionCustomerActionInCache1"));
            Assert.Single(customerOperations.Where(a => a.Name == "CollectionCustomerActionInCache2"));
            Assert.Single(customerOperations.Where(a => a.Name == "CollectionCustomerFunctionInCache1"));
            Assert.Single(customerOperations.Where(a => a.Name == "CollectionCustomerFunctionInCache2"));

            Assert.Equal(5, blockBusterOperations.Length);
            Assert.Single(blockBusterOperations.Where(a => a.Name == "CollectionBlockbusterActionInCache5"));
            Assert.Single(blockBusterOperations.Where(a => a.Name == "CollectionBlockbusterFunctionInCache5"));
            Assert.Single(blockBusterOperations.Where(a => a.Name == "CollectionMovieActionInCache3"));
            Assert.Single(blockBusterOperations.Where(a => a.Name == "CollectionMovieActionInCache4"));
            Assert.Single(blockBusterOperations.Where(a => a.Name == "CollectionMovieFunctionInCache3"));
        }
Esempio n. 27
0
        public void CanBuildBoundOperationCacheForIEdmModel()
        {
            // Arrange
            ODataModelBuilder builder = new ODataModelBuilder();
            EntityTypeConfiguration <Customer> customer = builder.EntitySet <Customer>("Customers").EntityType;

            customer.HasKey(c => c.ID);
            customer.Property(c => c.Name);
            customer.ComplexProperty(c => c.Address);

            EntityTypeConfiguration <Movie> movie = builder.EntitySet <Movie>("Movies").EntityType;

            movie.HasKey(m => m.ID);
            movie.HasKey(m => m.Name);
            EntityTypeConfiguration <Blockbuster> blockBuster = builder.EntityType <Blockbuster>().DerivesFrom <Movie>();
            EntityTypeConfiguration movieConfiguration        = builder.StructuralTypes.OfType <EntityTypeConfiguration>().Single(t => t.Name == "Movie");

            // build actions that are bindable to a single entity
            customer.Action("InCache1_CustomerAction");
            customer.Action("InCache2_CustomerAction");
            movie.Action("InCache3_MovieAction");
            ActionConfiguration incache4_MovieAction = builder.Action("InCache4_MovieAction");

            incache4_MovieAction.SetBindingParameter("bindingParameter", movieConfiguration);
            blockBuster.Action("InCache5_BlockbusterAction");

            // build actions that are either: bindable to a collection of entities, have no parameter, have only complex parameter
            customer.Collection.Action("NotInCache1_CustomersAction");
            movie.Collection.Action("NotInCache2_MoviesAction");
            ActionConfiguration notInCache3_NoParameters     = builder.Action("NotInCache3_NoParameters");
            ActionConfiguration notInCache4_AddressParameter = builder.Action("NotInCache4_AddressParameter");

            notInCache4_AddressParameter.Parameter <Address>("address");

            IEdmModel      model           = builder.GetEdmModel();
            IEdmEntityType customerType    = model.SchemaElements.OfType <IEdmEntityType>().Single(e => e.Name == "Customer");
            IEdmEntityType movieType       = model.SchemaElements.OfType <IEdmEntityType>().Single(e => e.Name == "Movie");
            IEdmEntityType blockBusterType = model.SchemaElements.OfType <IEdmEntityType>().Single(e => e.Name == "Blockbuster");

            // Act
            BindableOperationFinder annotation = new BindableOperationFinder(model);

            IEdmAction[] movieActions = annotation.FindOperations(movieType)
                                        .OfType <IEdmAction>()
                                        .ToArray();
            IEdmAction[] customerActions = annotation.FindOperations(customerType)
                                           .OfType <IEdmAction>()
                                           .ToArray();
            IEdmAction[] blockBusterActions = annotation.FindOperations(blockBusterType)
                                              .OfType <IEdmAction>()
                                              .ToArray();

            // Assert
            Assert.Equal(2, customerActions.Length);
            Assert.NotNull(customerActions.SingleOrDefault(a => a.Name == "InCache1_CustomerAction"));
            Assert.NotNull(customerActions.SingleOrDefault(a => a.Name == "InCache2_CustomerAction"));
            Assert.Equal(2, movieActions.Length);
            Assert.NotNull(movieActions.SingleOrDefault(a => a.Name == "InCache3_MovieAction"));
            Assert.NotNull(movieActions.SingleOrDefault(a => a.Name == "InCache4_MovieAction"));
            Assert.Equal(3, blockBusterActions.Length);
            Assert.NotNull(blockBusterActions.SingleOrDefault(a => a.Name == "InCache3_MovieAction"));
            Assert.NotNull(blockBusterActions.SingleOrDefault(a => a.Name == "InCache4_MovieAction"));
            Assert.NotNull(blockBusterActions.SingleOrDefault(a => a.Name == "InCache5_BlockbusterAction"));
        }