public void TryCreateFilterTest()
        {
            // Arrange.
            const string ReferencedProcessName = "CRProcess";
            const int Id1 = 111;
            const int Id2 = 222;
            var value1 = new object();
            var dataContext = Mock.Create<IDataContext>(Behavior.Loose);

            var filter1 = new ColumnFilter("TestField", null);
            var keyField1 = Mock.Create<IProcessFieldMapping>(Behavior.Loose);
            Mock.Arrange(() => keyField1.IsKey).Returns(true);
            Mock.Arrange(() => keyField1.TryCreateFilter(dataContext, out filter1)).Returns(true);


            var filter2 = new ColumnFilter("TestField", null);
            var keyField2 = Mock.Create<IProcessFieldMapping>(Behavior.Loose);
            Mock.Arrange(() => keyField2.IsKey).Returns(true);
            Mock.Arrange(() => keyField2.TryCreateFilter(dataContext, out filter2)).Returns(true);

            var dtm = new Mock<IDynamicTypeManager>();

            var runtimeDatabase = Mock.Create<IRuntimeDatabase>(Behavior.Loose);
            Mock.Arrange(() => runtimeDatabase.FindItems(ReferencedProcessName, Arg.IsAny<IEnumerable<ColumnFilter>>()))
                .Returns<string, IEnumerable<ColumnFilter>>(
                    (processName, filters) =>
                    {
                        var filtersArray = Enumerable.ToArray(filters);
                        if (filtersArray.Length == 1 && Enumerable.Contains(filtersArray, filter1))
                            return new Collection<int> { Id2 };

                        return new Collection<int>();
                    });

            var typeConverter = Mock.Create<ITypeConverter>(Behavior.Loose);
            Mock.Arrange(() => typeConverter.Convert<int?>(value1)).Returns(Id1);

            // CR field is mapped. Value is not null.
            var mapping = new SingleCrossReferenceFieldMapping(
                ReflectionHelper.GetProperty<TestEditable>(x => x.CR),
                dc => dc == dataContext ? value1 : null,
                false,
                typeConverter,
                dtm.Object,
                runtimeDatabase,
                null);

            ColumnFilter filter;

            // Act / Assert.
            Assert.IsTrue(mapping.TryCreateFilter(dataContext, out filter));
            Assert.AreEqual("CR", filter.ColumnName);
            Assert.AreEqual(Id1, filter.Value);

            // CR field is mapped. Value is null.
            mapping = new SingleCrossReferenceFieldMapping(
                ReflectionHelper.GetProperty<TestEditable>(x => x.CR),
                dc => null,
                false,
                typeConverter,
                dtm.Object,
                runtimeDatabase,
                null);

            // Act / Assert.
            Assert.IsFalse(mapping.TryCreateFilter(dataContext, out filter));

            // CR field has key fields. Value is found.
            mapping = new SingleCrossReferenceFieldMapping(
                ReflectionHelper.GetProperty<TestEditable>(x => x.CR),
                null,
                false,
                typeConverter,
                dtm.Object,
                runtimeDatabase,
                new[] { keyField1 });

            // Act / Assert.
            Assert.IsTrue(mapping.TryCreateFilter(dataContext, out filter));
            Assert.AreEqual("CR", filter.ColumnName);
            Assert.AreEqual(Id2, filter.Value);

            // CR field has key fields. Value is not found.
            mapping = new SingleCrossReferenceFieldMapping(
                ReflectionHelper.GetProperty<TestEditable>(x => x.CR),
                null,
                false,
                typeConverter,
                dtm.Object,
                runtimeDatabase,
                new[] { keyField2 });

            // Act / Assert.
            Assert.IsFalse(mapping.TryCreateFilter(dataContext, out filter));
        }
        public void UpdateTest()
        {
            // Arrange.
            const int CrId1 = 111;
            const int CrId2 = 222;
            const string ReferencedProcessName = "CRProcess";

            var value1 = new object();
            var dataContext = Mock.Create<IDataContext>(Behavior.Loose);

            var typeConverter = new Mock<ITypeConverter>();
            typeConverter.Setup(x => x.Convert<int?>(value1)).Returns(CrId1);

            var filter = new ColumnFilter("TestField", null);

            var keyField = Mock.Create<IProcessFieldMapping>(Behavior.Loose);
            Mock.Arrange(() => keyField.IsKey).Returns(true);
            Mock.Arrange(() => keyField.TryCreateFilter(dataContext, out filter)).Returns(true);

            var dtm = new Mock<IDynamicTypeManager>();

            var runtimeDatabase = Mock.Create<IRuntimeDatabase>(Behavior.Loose);
            Mock.Arrange(() => runtimeDatabase.FindItems(ReferencedProcessName, Arg.IsAny<IEnumerable<ColumnFilter>>()))
                .Returns<string, IEnumerable<ColumnFilter>>(
                    (processName, filters) =>
                    {
                        var filtersArray = filters.ToArray();
                        if (filtersArray.Length == 1 && filtersArray.Contains(filter))
                            return new Collection<int> { CrId2 };

                        return new Collection<int>();
                    });

            // Update with direct value.
            var mapping = new SingleCrossReferenceFieldMapping(
                ReflectionHelper.GetProperty<TestEditable>(x => x.CR),
                dc => dc == dataContext ? value1 : null,
                false,
                typeConverter.Object,
                dtm.Object,
                runtimeDatabase,
                null);
            var editItem = new TestEditable();

            // Act.
            mapping.Update(dataContext, editItem);

            // Assert.
            Assert.AreEqual(CrId1, editItem.CR);

            // Update with key subfields.
            mapping = new SingleCrossReferenceFieldMapping(
                ReflectionHelper.GetProperty<TestEditable>(x => x.CR),
                null,
                false,
                typeConverter.Object,
                dtm.Object,
                runtimeDatabase,
                new[] { keyField });

            editItem = new TestEditable();

            // Act.
            mapping.Update(dataContext, editItem);

            // Assert.
            Assert.AreEqual(CrId2, editItem.CR);
        }