public void NamedUpdate_CustomValidation_NoEntityValidation()
        {
            string methodName = "NamedUpdateWithNoEntityValidation";
            MockComplexObject2 complexObject = new MockComplexObject2();

            string format1 = "{0} invalid on client.";
            ValidationResult registeredResult = CustomMethodTests.CreateRegisteredValidationResult(format1, typeof(MockComplexObject2));
            ValidationResult expectedClientResult = CustomMethodTests.CreateExpectedValidationResult(format1, typeof(MockComplexObject2), true, methodName + ".complexObject.PlaceholderName");

            SubmitOperation submitOp = null;
            LoadOperation<MockEntity6> loadOp = null;
            MockEntity6 entity = null;

            Uri uri = new Uri(TestURIs.RootURI, "TestDomainServices-NamedUpdates-NamedUpdate_CustomValidation.svc");
            NamedUpdate_CustomValidation ctx = null;

            this.EnqueueCallback(() =>
                {
                    ctx = new NamedUpdate_CustomValidation(uri);
                    loadOp = ctx.Load(ctx.GetEntities6Query(), TestHelperMethods.DefaultOperationAction, null);
                });

            this.EnqueueConditional(() => loadOp.IsComplete);

            this.EnqueueCallback(() =>
                {
                    TestHelperMethods.AssertOperationSuccess(loadOp);
                    entity = loadOp.Entities.First();

                    // Make the param invalid and the call should fail.
                    DynamicTestValidator.ForcedValidationResults.Add(typeof(MockComplexObject2), registeredResult);
                    ExceptionHelper.ExpectValidationException(() =>
                        {
                            entity.NamedUpdateWithNoEntityValidation(complexObject);
                        }, expectedClientResult.ErrorMessage, typeof(CustomValidationAttribute), complexObject);

                    DynamicTestValidator.Reset();
                    entity.NamedUpdateWithNoEntityValidation(complexObject);

                    // This time the client submit should fail.
                    DynamicTestValidator.ForcedValidationResults.Add(typeof(MockComplexObject2), registeredResult);
                    submitOp = ctx.SubmitChanges(TestHelperMethods.DefaultOperationAction, null);
                });

            this.EnqueueConditional(() => submitOp.IsComplete);

            this.EnqueueCallback(() =>
                {
                    Assert.IsTrue(submitOp.HasError, "Client call: Submit should have failed.");
                    UnitTestHelper.AssertValidationResultsAreEqual(new ValidationResult[] { expectedClientResult }, entity.ValidationErrors);

                    // Now the server submit should fail.
                    DynamicTestValidator.Reset();
                    submitOp = ctx.SubmitChanges(TestHelperMethods.DefaultOperationAction, null);
                });

            this.EnqueueConditional(() => submitOp.IsComplete);

            this.EnqueueCallback(() =>
                {
                    Assert.IsTrue(submitOp.HasError, "Server call: Submit should have failed.");
                    var expectedServerResults = CustomMethodTests.GetExpectedErrors(methodName);
                    UnitTestHelper.AssertValidationResultsAreEqual(expectedServerResults, entity.ValidationErrors);
                });

            this.EnqueueTestComplete();
        }
        public void NamedUpdate_CustomValidation_CommonProperties()
        {
            string methodName = "NamedUpdateWithCommonProperties";
            MockComplexObject3 complexObject = CustomMethodTests.CreateMockComplexObject3();

            SubmitOperation submitOp = null;
            LoadOperation<MockEntity5> loadOp = null;
            MockEntity5 entity = null;

            Uri uri = new Uri(TestURIs.RootURI, "TestDomainServices-NamedUpdates-NamedUpdate_CustomValidation.svc");
            NamedUpdate_CustomValidation ctx = null;

            Action<MockComplexObject4, ValidationResult, ValidationResult> paramVariation =
                (invalidObject, registeredResult, expectedClientResult) =>
                {
                    this.EnqueueCallback(() =>
                        {
                            ctx = new NamedUpdate_CustomValidation(uri);
                            loadOp = ctx.Load(ctx.GetEntities5Query(), TestHelperMethods.DefaultOperationAction, null);
                        });

                    this.EnqueueConditional(() => loadOp.IsComplete);

                    this.EnqueueCallback(() =>
                        {
                            TestHelperMethods.AssertOperationSuccess(loadOp);
                            entity = loadOp.Entities.First();
                            entity.NamedUpdateWithCommonProperties(complexObject);

                            // Make only the ComplexObject's property invalid. This should produce an error
                            // that can't be pushed down into the entity's property's collection.
                            DynamicTestValidator.ForcedValidationResults.Add(invalidObject, registeredResult);

                            // Submit and watch it fail.
                            submitOp = ctx.SubmitChanges(TestHelperMethods.DefaultOperationAction, null);
                        });

                    this.EnqueueConditional(() => submitOp.IsComplete);

                    this.EnqueueCallback(() =>
                        {
                            Assert.IsTrue(submitOp.HasError, "Client call: Submit should have failed.");

                            // The client should fail validation of only the argument's property.
                            Assert.AreEqual(1, entity.ValidationErrors.Count(), "Client call: Entity should have an error.");
                            Assert.AreEqual(0, entity.CommonProperty.ValidationErrors.Count(), "Client call: Validation error was pushed down to property.");
                            Assert.AreEqual(0, entity.CommonArray[0].ValidationErrors.Count(), "Client call: Validation error was pushed down to array.");

                            // Reset the validator and get the result from the server.
                            DynamicTestValidator.Reset();
                            submitOp = ctx.SubmitChanges(TestHelperMethods.DefaultOperationAction, null);
                        });

                    this.EnqueueConditional(() => submitOp.IsComplete);

                    this.EnqueueCallback(() =>
                        {
                            Assert.IsTrue(submitOp.HasError, "Server call: Submit should have failed.");
                            // The server should fail validation of all MockEntity4 types.
                            IEnumerable<ValidationResult> expectedServerValidationResults = CustomMethodTests.GetExpectedErrors(methodName);
                            UnitTestHelper.AssertValidationResultsAreEqual(expectedServerValidationResults, entity.ValidationResultCollection);
                            Assert.AreEqual(1, entity.CommonProperty.ValidationErrors.Count(), "Server call: Validation error was pushed down to property.");

                            // Errors cannot get pushed to arrays.
                            Assert.AreEqual(0, entity.CommonArray[0].ValidationErrors.Count(), "Server call: Validation error was pushed down to array.");
                        });
                };

            string format1 = "{0} invalid on client.";
            string paramPrefix = methodName + ".complexObject.";
            paramVariation(complexObject.CommonProperty,
                CustomMethodTests.CreateRegisteredValidationResult(format1, typeof(MockComplexObject4), "CommonProperty.PlacehoderName"),
                CustomMethodTests.CreateExpectedValidationResult(format1, typeof(MockComplexObject4), false, "CommonProperty.PlacehoderName"));
            paramVariation(complexObject.CommonProperty.Property1,
                CustomMethodTests.CreateRegisteredValidationResult(format1, typeof(MockComplexObject4), "CommonProperty.Property1.PlacehoderName"),
                CustomMethodTests.CreateExpectedValidationResult(format1, typeof(MockComplexObject4), false, "CommonProperty.Property1.PlacehoderName"));
            paramVariation(complexObject.CommonArray[0],
                CustomMethodTests.CreateRegisteredValidationResult(format1, typeof(MockComplexObject4), "CommonArray().PlacehoderName"),
                CustomMethodTests.CreateExpectedValidationResult(format1, typeof(MockComplexObject4), false, paramPrefix + "CommonArray().PlacehoderName"));
            paramVariation(complexObject.CommonArray[0].Property1,
                CustomMethodTests.CreateRegisteredValidationResult(format1, typeof(MockComplexObject4), "CommonArray().Property1.PlacehoderName"),
                CustomMethodTests.CreateExpectedValidationResult(format1, typeof(MockComplexObject4), false, paramPrefix + "CommonArray().Property1.PlacehoderName"));

            this.EnqueueTestComplete();
        }
        public void NamedUpdate_CustomValidation_Property()
        {
            MockComplexObject1[] complexArray = new MockComplexObject1[] { new MockComplexObject1() { } };
            MockComplexObject1 complexObject = new MockComplexObject1 { Property1 = new MockComplexObject1() };

            SubmitOperation submitOp = null;
            LoadOperation<MockEntity3> loadOp = null;
            MockEntity3 entity = null;

            Uri uri = new Uri(TestURIs.RootURI, "TestDomainServices-NamedUpdates-NamedUpdate_CustomValidation.svc");
            NamedUpdate_CustomValidation ctx = null;

            Action<object, ValidationResult, ValidationResult, ValidationResult> paramVariation =
                (invalidParam, registeredResult, expectedClientResult, expectedServerResult) =>
                {
                    this.EnqueueCallback(() =>
                    {
                        ctx = new NamedUpdate_CustomValidation(uri);
                        loadOp = ctx.Load(ctx.GetEntities3Query(), TestHelperMethods.DefaultOperationAction, null);
                    });

                    this.EnqueueConditional(() => loadOp.IsComplete);

                    this.EnqueueCallback(() =>
                    {
                        TestHelperMethods.AssertOperationSuccess(loadOp);
                        entity = loadOp.Entities.First();

                        // reset property values
                        entity.ValidatedProperty = null;
                        complexArray[0].ValidatedProperty = null;
                        complexObject.ValidatedProperty = null;
                        complexObject.Property1.ValidatedProperty = null;

                        // make the correct param invalid.
                        string invalidProperty = "Invalid";
                        bool deepValidation;
                        if (invalidParam == null)
                        {
                            entity.ValidatedProperty = invalidProperty;
                            deepValidation = false;
                        }
                        else if (invalidParam == complexArray)
                        {
                            complexArray[0].ValidatedProperty = invalidProperty;
                            deepValidation = true;
                        }
                        else if (invalidParam == complexObject)
                        {
                            complexObject.ValidatedProperty = invalidProperty;
                            deepValidation = false;
                        }
                        else
                        {
                            complexObject.Property1.ValidatedProperty = invalidProperty;
                            deepValidation = true;
                        }

                        // make property invalid
                        DynamicTestValidator.Reset();
                        DynamicTestValidator.ForcedValidationResults.Add(invalidProperty, registeredResult);

                        // deep property validation should not throw on call
                        if (deepValidation)
                        {
                            entity.NamedUpdateWithPropValidation(complexArray, complexObject);
                            ctx.MockEntity3s.Clear();
                            entity.Reset();
                            ctx.MockEntity3s.Attach(entity);
                        }
                        // shallow property validation should throw on call
                        else
                        {
                            ValidationException vex = ExceptionHelper.ExpectValidationException(() =>
                            {
                                entity.NamedUpdateWithPropValidation(complexArray, complexObject);
                            }, expectedClientResult.ErrorMessage, typeof(CustomValidationAttribute), invalidProperty);
                            // The exception varies from the expected because the framework does not alter the result.
                            // This means the expected MemberNames is equivalent to the registered MemberNames
                            UnitTestHelper.AssertValidationResultsAreEqual(new ValidationResult[] { new ValidationResult(expectedClientResult.ErrorMessage, registeredResult.MemberNames) }, new ValidationResult[] { vex.ValidationResult });
                        }

                        // ensure property validation fails on client submit
                        DynamicTestValidator.Reset();
                        entity.NamedUpdateWithPropValidation(complexArray, complexObject);

                        // make param invalid once again
                        DynamicTestValidator.ForcedValidationResults.Add(invalidProperty, registeredResult);

                        // actually submit
                        submitOp = ctx.SubmitChanges(TestHelperMethods.DefaultOperationAction, null);
                    });

                    this.EnqueueConditional(() => submitOp.IsComplete);

                    this.EnqueueCallback(() =>
                    {
                        Assert.IsTrue(submitOp.HasError, "No error on client submit of an incorrect entity.");

                        // compare to expected
                        UnitTestHelper.AssertValidationResultsAreEqual(new ValidationResult[] { expectedClientResult }, entity.ValidationResultCollection);

                        // ensure property validation fails on server submit
                        DynamicTestValidator.Reset();
                        submitOp = ctx.SubmitChanges(TestHelperMethods.DefaultOperationAction, null);
                    });

                    this.EnqueueConditional(() => submitOp.IsComplete);

                    this.EnqueueCallback(() =>
                    {
                        Assert.IsTrue(submitOp.HasError, "No error on server submit of an incorrect entity.");

                        // compare to expected
                        IEnumerable<ValidationResult> expectedServerValidationResults = new ValidationResult[] { expectedServerResult };
                        UnitTestHelper.AssertValidationResultsAreEqual(expectedServerValidationResults, entity.ValidationResultCollection);
                    });
                };

            // Run variations
            string clientFormat1 = "{0} invalid on the client";
            string propName = "ValidatedProperty";
            string serverErrorMessage = DynamicTestValidator.GetMemberError("Property validation failed.", propName);
            string methodName = "NamedUpdateWithPropValidation.";

            paramVariation(null,
                CustomMethodTests.CreateRegisteredValidationResult(clientFormat1, propName),
                CustomMethodTests.CreateExpectedPropertyValidationResult(clientFormat1, propName),
                CustomMethodTests.CreateExpectedValidationResult(serverErrorMessage, propName));

            string memberPath = methodName + "array()";
            paramVariation(complexArray,
                CustomMethodTests.CreateRegisteredValidationResult(clientFormat1, propName),
                CustomMethodTests.CreateExpectedPropertyValidationResult(clientFormat1, propName, memberPath),
                CustomMethodTests.CreateExpectedValidationResult(serverErrorMessage, propName, memberPath));

            memberPath = methodName + "complexObject";
            paramVariation(complexObject,
                CustomMethodTests.CreateRegisteredValidationResult(clientFormat1, propName),
                CustomMethodTests.CreateExpectedPropertyValidationResult(clientFormat1, propName, memberPath),
                CustomMethodTests.CreateExpectedValidationResult(serverErrorMessage, propName, memberPath));

            memberPath = methodName + "complexObject.Property1";
            paramVariation(complexObject.Property1,
                CustomMethodTests.CreateRegisteredValidationResult(clientFormat1, propName),
                CustomMethodTests.CreateExpectedPropertyValidationResult(clientFormat1, propName, memberPath),
                CustomMethodTests.CreateExpectedValidationResult(serverErrorMessage, propName, memberPath));

            this.EnqueueTestComplete();
        }
        public void NamedUpdate_CustomValidation_Type()
        {
            MockComplexObject2[] complexArray = new MockComplexObject2[] { new MockComplexObject2() };
            MockComplexObject2 complexObject = new MockComplexObject2 { Property1 = new MockComplexObject2() };

            SubmitOperation submitOp = null;
            LoadOperation<MockEntity4> loadOp = null;
            MockEntity4 entity = null;

            Uri uri = new Uri(TestURIs.RootURI, "TestDomainServices-NamedUpdates-NamedUpdate_CustomValidation.svc");
            NamedUpdate_CustomValidation ctx = null;

            Action<object, bool, ValidationResult, ValidationResult> typeVariation = (invalidParam, deepValidation, registeredResult, expectedResult) =>
            {
                this.EnqueueCallback(() =>
                {
                    ctx = new NamedUpdate_CustomValidation(uri);
                    loadOp = ctx.Load(ctx.GetEntities4Query(), TestHelperMethods.DefaultOperationAction, null);
                });

                this.EnqueueConditional(() => loadOp.IsComplete);

                this.EnqueueCallback(() =>
                {
                    TestHelperMethods.AssertOperationSuccess(loadOp);
                    entity = loadOp.Entities.First();

                    if (invalidParam == null)
                    {
                        invalidParam = entity;
                    }

                    // make param invalid
                    DynamicTestValidator.Reset();
                    DynamicTestValidator.ForcedValidationResults.Add(invalidParam, registeredResult);

                    // deep type validation should not throw on call
                    if (deepValidation)
                    {
                        entity.NamedUpdateWithTypeValidation(complexArray, complexObject);
                        ctx.MockEntity4s.Clear();
                        entity.Reset();
                        ctx.MockEntity4s.Attach(entity);
                    }
                    // shallow type validation should throw on call
                    else
                    {
                        ValidationException vex = ExceptionHelper.ExpectValidationException(() =>
                        {
                            entity.NamedUpdateWithTypeValidation(complexArray, complexObject);
                        }, expectedResult.ErrorMessage, typeof(CustomValidationAttribute), invalidParam);
                        // The exception varies from the expected because the framework does not alter the result.
                        // This means the expected MemberNames is equivalent to the registered MemberNames
                        UnitTestHelper.AssertValidationResultsAreEqual(new ValidationResult[] { new ValidationResult(expectedResult.ErrorMessage, registeredResult.MemberNames) }, new ValidationResult[] { vex.ValidationResult });
                    }

                    // ensure type validation fails on client submit
                    DynamicTestValidator.Reset();
                    entity.NamedUpdateWithTypeValidation(complexArray, complexObject);

                    // make param invalid once again
                    DynamicTestValidator.ForcedValidationResults.Add(invalidParam, registeredResult);

                    // actually submit
                    submitOp = ctx.SubmitChanges(TestHelperMethods.DefaultOperationAction, null);
                });

                this.EnqueueConditional(() => submitOp.IsComplete);

                this.EnqueueCallback(() =>
                {
                    Assert.IsTrue(submitOp.HasError, "No error on client submit of an incorrect entity.");

                    // compare to expected
                    UnitTestHelper.AssertValidationResultsAreEqual(new ValidationResult[] { expectedResult }, entity.ValidationResultCollection);

                    // ensure type validation fails on server submit
                    DynamicTestValidator.Reset();
                    submitOp = ctx.SubmitChanges(TestHelperMethods.DefaultOperationAction, null);
                });

                this.EnqueueConditional(() => submitOp.IsComplete);

                this.EnqueueCallback(() =>
                {
                    Assert.IsTrue(submitOp.HasError, "No error on server submit of an incorrect entity.");

                    // compare to expected, the server errors no matter what we send it, so its
                    // expected validation failures can be static.
                    IEnumerable<ValidationResult> expectedServerValidationResults = CustomMethodTests.GetExpectedErrors("NamedUpdateWithTypeValidation");
                    UnitTestHelper.AssertValidationResultsAreEqual(expectedServerValidationResults, entity.ValidationResultCollection);
                });
            };

            // Run variations
            string format1 = "{0} invalid on the client";
            typeVariation(null, false,
                CustomMethodTests.CreateRegisteredValidationResult(format1, typeof(MockEntity4)),
                CustomMethodTests.CreateExpectedValidationResult(format1, typeof(MockEntity4), false));

            typeVariation(complexArray[0], true,
                CustomMethodTests.CreateRegisteredValidationResult(format1, typeof(MockComplexObject2)),
                CustomMethodTests.CreateExpectedValidationResult(format1, typeof(MockComplexObject2), false, "NamedUpdateWithTypeValidation.array().PlaceholderName"));

            typeVariation(complexObject, false,
                CustomMethodTests.CreateRegisteredValidationResult(format1, typeof(MockComplexObject2)),
                CustomMethodTests.CreateExpectedValidationResult(format1, typeof(MockComplexObject2), false, "NamedUpdateWithTypeValidation.complexObject.PlaceholderName"));
            
            typeVariation(complexObject.Property1, true,
                CustomMethodTests.CreateRegisteredValidationResult(format1, typeof(MockComplexObject2)),
                CustomMethodTests.CreateExpectedValidationResult(format1, typeof(MockComplexObject2), false, "NamedUpdateWithTypeValidation.complexObject.Property1.PlaceholderName"));

            this.EnqueueTestComplete();
        }
        public void NamedUpdate_CustomValidation_Parameter()
        {
            MockComplexObject1[] complexArray = new MockComplexObject1[] { new MockComplexObject1() };
            MockComplexObject1 complexObject = new MockComplexObject1 { Property1 = new MockComplexObject1() };

            Uri uri = new Uri(TestURIs.RootURI, "TestDomainServices-NamedUpdates-NamedUpdate_CustomValidation.svc");
            NamedUpdate_CustomValidation ctx = null;
            MockEntity3 entity = null;
            LoadOperation<MockEntity3> loadOp = null;
            SubmitOperation submitOp = null;

            // The core body of the test. This delegate can be called multiple times.
            Action<object, ValidationResult, ValidationResult> paramVariation = (invalidParam, registeredResult, expectedResult) =>
            {
                this.EnqueueCallback(() =>
                {
                    ctx = new NamedUpdate_CustomValidation(uri);
                    loadOp = ctx.Load(ctx.GetEntities3Query(), TestHelperMethods.DefaultOperationAction, null);
                });

                this.EnqueueConditional(() => loadOp.IsComplete);

                this.EnqueueCallback(() =>
                {
                    TestHelperMethods.AssertOperationSuccess(loadOp);
                    entity = loadOp.Entities.First();

                    // make param invalid
                    DynamicTestValidator.Reset();
                    DynamicTestValidator.ForcedValidationResults.Add(invalidParam.GetType(), registeredResult);

                    // param validation should throw on call
                    ValidationException vex = ExceptionHelper.ExpectValidationException(() =>
                    {
                        entity.NamedUpdateWithParamValidation(complexArray, complexObject);
                    }, expectedResult.ErrorMessage, typeof(CustomValidationAttribute), invalidParam);
                    // The exception varies from the expected because the framework does not alter the result.
                    // This means the expected MemberNames is equivalent to the registered MemberNames
                    UnitTestHelper.AssertValidationResultsAreEqual(new ValidationResult[] { new ValidationResult(expectedResult.ErrorMessage, registeredResult.MemberNames) }, new ValidationResult[] { vex.ValidationResult });

                    // ensure param validation fails on client submit
                    DynamicTestValidator.Reset();
                    entity.NamedUpdateWithParamValidation(complexArray, complexObject);

                    // make param invalid once again
                    DynamicTestValidator.ForcedValidationResults.Add(invalidParam.GetType(), registeredResult);

                    // actually submit
                    submitOp = ctx.SubmitChanges(TestHelperMethods.DefaultOperationAction, null);
                });

                this.EnqueueConditional(() => submitOp.IsComplete);

                this.EnqueueCallback(() =>
                {
                    Assert.IsTrue(submitOp.HasError, "No error on client submit of an incorrect param.");

                    // compare to expected
                    UnitTestHelper.AssertValidationResultsAreEqual(new ValidationResult[] { expectedResult }, entity.ValidationResultCollection);

                    // ensure param validation fails on server submit
                    DynamicTestValidator.Reset();
                    submitOp = ctx.SubmitChanges(TestHelperMethods.DefaultOperationAction, null);
                });

                this.EnqueueConditional(() => submitOp.IsComplete);

                this.EnqueueCallback(() =>
                {
                    Assert.IsTrue(submitOp.HasError, "No error on server submit of an incorrect param.");

                    // compare to expected, the server errors no matter what we send it, so its
                    // expected validation failures can be static.
                    IEnumerable<ValidationResult> expectedServerValidationResults = CustomMethodTests.GetExpectedErrors("NamedUpdateWithParamValidation");
                    UnitTestHelper.AssertValidationResultsAreEqual(expectedServerValidationResults, entity.ValidationResultCollection);
                });
            };

            string format1 = "{0} invalid on the client";

            // Run variations
            paramVariation(complexArray,
                CreateRegisteredValidationResult(format1, complexArray.GetType()),
                CreateExpectedValidationResult(format1, complexArray.GetType(), true, "NamedUpdateWithParamValidation.array().PlaceholderName"));

            paramVariation(complexObject,
                CreateRegisteredValidationResult(format1, complexObject.GetType()),
                CreateExpectedValidationResult(format1, complexObject.GetType(), true, "NamedUpdateWithParamValidation.complexObject.PlaceholderName"));

            this.EnqueueTestComplete();
        }
        public void NamedUpdate_CustomValidation_Entity_Parameter()
        {
            string clientInvalidProperty = "Invalid on client";
            MockComplexObject1[] complexArray = new MockComplexObject1[] { new MockComplexObject1() };
            MockComplexObject1 recursiveComplexObject = new MockComplexObject1 { Property1 = new MockComplexObject1() };
            string[] memberNames = new string[] { "PlaceholderName" };
            ValidationResult expectedClientValidationResult = new ValidationResult(clientInvalidProperty, memberNames);

            Uri uri = new Uri(TestURIs.RootURI, "TestDomainServices-NamedUpdates-NamedUpdate_CustomValidation.svc");
            NamedUpdate_CustomValidation ctx = new NamedUpdate_CustomValidation(uri);
            MockEntity3 entity = null;
            LoadOperation<MockEntity3> loadOp = null;
            SubmitOperation submitOp = null;

            this.EnqueueCallback(() =>
            {
                loadOp = ctx.Load(ctx.GetEntities3Query(), TestHelperMethods.DefaultOperationAction, null);
            });

            this.EnqueueConditional(() => loadOp.IsComplete);

            this.EnqueueCallback(() =>
            {
                TestHelperMethods.AssertOperationSuccess(loadOp);
                entity = loadOp.Entities.First();

                // make entity param invalid
                DynamicTestValidator.Reset();
                DynamicTestValidator.ForcedValidationResults.Add(typeof(MockEntity3), expectedClientValidationResult);
                DynamicTestValidator.Monitor(true);

                // entity param validation should not be run during the call
                entity.NamedUpdateWithParamValidation(complexArray, recursiveComplexObject);

                // entity param validation should not be run during the submit on the client side
                submitOp = ctx.SubmitChanges(TestHelperMethods.DefaultOperationAction, null);
            });

            this.EnqueueConditional(() => submitOp.IsComplete);

            this.EnqueueCallback(() =>
            {
                // the server fails all params
                Assert.IsTrue(submitOp.HasError, "Error on client submit of an incorrect entity.");

                // check that param validation was not run on the client
                // note, entity has no param name so we cannot check for it directly
                Assert.IsFalse(DynamicTestValidator.ValidationCalls.Where(vc =>
                    vc.DisplayName != "array"
                    && vc.DisplayName != "complexObject"
                    && vc.DisplayName != "ValidatedProperty").Any(), "Entity underwent param validation.");

                // check that the param validtion was run on the server
                IEnumerable<ValidationResult> expectedServerValidationResult = CustomMethodTests.GetExpectedErrors("NamedUpdateWithParamValidation");
                UnitTestHelper.AssertValidationResultsAreEqual(expectedServerValidationResult, entity.ValidationResultCollection);
            });

            this.EnqueueTestComplete();
        }