public void UpdateCanInsertItems()
        {
            // Arrange.
            const string ProcessName = "TestProcess";
            const string DestinationFieldName = "TestField";
            const string ReferencedProcessName = "RefProcess";
            const string FieldName1 = "Field1";
            const string FieldName2 = "Field2";

            var dataSourceDefinition = new FieldMappingDataSourceDefinition("Test Data Source", ProcessName, "TestProperty", true, true, true);
            var fieldMapping1 = new DataTriggerFieldMapping(FieldName1, true, (s, d) => null);
            var fieldMapping2 = new DataTriggerFieldMapping(FieldName2, false, (s, d) => null);
            var mapping = new DataTriggerListFieldMapping(new[] { dataSourceDefinition }, DestinationFieldName, DataTriggerModificationType.Insert, new[] { fieldMapping1, fieldMapping2 });

            var dtm = Mock.Create<IDynamicTypeManager>();
            Mock.Arrange(() => dtm.GetEditableRootType(ProcessName)).Returns(typeof(DestinationEdit));

            var item = Mock.Create<IEditableRoot>();

            var sourceData1 = new DataTriggerSourceData();
            var sourceData2 = new DataTriggerSourceData();

            var sourceDataRetriever = Mock.Create<IFieldMappingSourceDataRetriever>();
            Mock.Arrange(() => sourceDataRetriever.GetSourceData(item, null)).Returns(() => new[] { sourceData1, sourceData2 });

            var savedDestinationItem1 = Mock.Create<IEditableRoot>();
            Mock.Arrange(() => savedDestinationItem1.Id).Returns(111);
            var newDestinationItem1 = Mock.Create<IEditableRootStub>();
            var savableDestinationItem1 = newDestinationItem1 as ISavable;
            Mock.Arrange(() => savableDestinationItem1.Save()).Returns(savedDestinationItem1);

            var savedDestinationItem2 = Mock.Create<IEditableRoot>();
            Mock.Arrange(() => savedDestinationItem2.Id).Returns(222);
            var newDestinationItem2 = Mock.Create<IEditableRootStub>();
            var savableDestinationItem2 = newDestinationItem2 as ISavable;
            Mock.Arrange(() => savableDestinationItem2.Save()).Returns(savedDestinationItem2);

            var newDestinationItems = new Queue<IEditableRoot>(new[] { newDestinationItem1, newDestinationItem2 });

            Mock.Arrange(() => dtm.NewEditableRoot<IEditableRoot>(ReferencedProcessName)).Returns(newDestinationItems.Dequeue);

            var fieldUpdater1 = Mock.Create<IFieldUpdater>();
            Mock.Arrange(() => fieldUpdater1.IsKey).Returns(true);
            var fieldUpdater2 = Mock.Create<IFieldUpdater>();

            var fieldUpdaterFactory = Mock.Create<IFieldUpdaterFactory>();
            Mock.Arrange(() => fieldUpdaterFactory.CreateFieldUpdater(ReferencedProcessName, fieldMapping1)).Returns(fieldUpdater1);
            Mock.Arrange(() => fieldUpdaterFactory.CreateFieldUpdater(ReferencedProcessName, fieldMapping2)).Returns(fieldUpdater2);

            var updater = new MultiCrossReferenceFieldUpdater
                              {
                                  DynamicTypeManager = dtm,
                                  FieldUpdaterFactory = fieldUpdaterFactory,
                                  SourceDataRetrieverFactory =
                                      new ExportFactory<IFieldMappingSourceDataRetriever>(
                                      () => new Tuple<IFieldMappingSourceDataRetriever, Action>(sourceDataRetriever, () => { }))
                              };

            updater.Initialize(ProcessName, mapping);

            var destination = new DestinationEdit();

            // Act.
            updater.BeforeItemUpdate(item, null);
            updater.AfterItemUpdate(item, null);
            updater.Update(item, destination);

            // Assert.
            Assert.AreEqual(2, destination.TestField.Count);
            Assert.IsTrue(destination.TestField.Any(x => x.Id == 111));
            Assert.IsTrue(destination.TestField.Any(x => x.Id == 222));

            Mock.Assert(() => fieldUpdater1.CalculateNewValue(sourceData1, newDestinationItem1), Occurs.Once());
            Mock.Assert(() => fieldUpdater1.Update(newDestinationItem1), Occurs.Once());

            Mock.Assert(() => fieldUpdater1.CalculateNewValue(sourceData2, newDestinationItem2), Occurs.Once());
            Mock.Assert(() => fieldUpdater1.Update(newDestinationItem2), Occurs.Once());

            Mock.Assert(() => fieldUpdater2.CalculateNewValue(sourceData1, newDestinationItem1), Occurs.Once());
            Mock.Assert(() => fieldUpdater2.Update(newDestinationItem1), Occurs.Once());

            Mock.Assert(() => fieldUpdater2.CalculateNewValue(sourceData2, newDestinationItem2), Occurs.Once());
            Mock.Assert(() => fieldUpdater2.Update(newDestinationItem2), Occurs.Once());

            Mock.Assert(() => savableDestinationItem1.Save(), Occurs.Once());
            Mock.Assert(() => savableDestinationItem2.Save(), Occurs.Once());
        }
        public void UpdateCanRemoveItems()
        {
            // Arrange.
            const string ProcessName = "TestProcess";
            const string DestinationFieldName = "TestField";
            const string ReferencedProcessName = "RefProcess";
            const string FieldName1 = "Field1";
            const string FieldName2 = "Field2";

            var dataSourceDefinition = new FieldMappingDataSourceDefinition("Test Data Source", ProcessName, "TestProperty", true, true, true);
            var fieldMapping1 = new DataTriggerFieldMapping(FieldName1, true, (s, d) => null);
            var fieldMapping2 = new DataTriggerFieldMapping(FieldName2, false, (s, d) => null);
            var mapping = new DataTriggerListFieldMapping(
                new[] { dataSourceDefinition }, DestinationFieldName, DataTriggerModificationType.Remove, new[] { fieldMapping1, fieldMapping2 });

            var item = Mock.Create<IEditableRoot>();

            var sourceData1 = new DataTriggerSourceData();
            var sourceData2 = new DataTriggerSourceData();
            var sourceData3 = new DataTriggerSourceData();

            var sourceDataRetriever = Mock.Create<IFieldMappingSourceDataRetriever>();
            Mock.Arrange(() => sourceDataRetriever.GetSourceData(item, null)).Returns(() => new[] { sourceData1, sourceData2, sourceData3 });

            var oldDestinationItem1 = Mock.Create<IEditableRoot>();
            Mock.Arrange(() => oldDestinationItem1.Id).Returns(111);

            var oldDestinationItem2 = Mock.Create<IEditableRoot>();
            Mock.Arrange(() => oldDestinationItem2.Id).Returns(222);

            var destination = new DestinationEdit();
            destination.TestField.Assign(oldDestinationItem1.Id);
            destination.TestField.Assign(oldDestinationItem2.Id);

            Mock.Arrange(() => _dtm.GetEditableRootType(ProcessName)).Returns(typeof(DestinationEdit));
            SetupGetEditableRoot(ReferencedProcessName, oldDestinationItem1, oldDestinationItem2);

            var fieldUpdater1 = Mock.Create<IFieldUpdater>();
            Mock.Arrange(() => fieldUpdater1.IsKey).Returns(true);
            var fieldUpdater2 = Mock.Create<IFieldUpdater>();

            var fieldUpdaterFactory = Mock.Create<IFieldUpdaterFactory>();
            Mock.Arrange(() => fieldUpdaterFactory.CreateFieldUpdater(ReferencedProcessName, fieldMapping1)).Returns(fieldUpdater1);
            Mock.Arrange(() => fieldUpdaterFactory.CreateFieldUpdater(ReferencedProcessName, fieldMapping2)).Returns(fieldUpdater2);

            Mock.Arrange(() => fieldUpdater1.AreEqual(sourceData1, oldDestinationItem1)).Returns(true);

            var updater = new MultiCrossReferenceFieldUpdater
                              {
                                  DynamicTypeManager = _dtm,
                                  FieldUpdaterFactory = fieldUpdaterFactory,
                                  SourceDataRetrieverFactory =
                                      new ExportFactory<IFieldMappingSourceDataRetriever>(
                                      () => new Tuple<IFieldMappingSourceDataRetriever, Action>(sourceDataRetriever, () => { }))
                              };

            updater.Initialize(ProcessName, mapping);

            // Act.
            updater.BeforeItemUpdate(item, null);
            updater.AfterItemUpdate(item, null);
            updater.Update(item, destination);

            // Assert.
            Assert.AreEqual(1, destination.TestField.Count);
            Assert.IsTrue(destination.TestField.Any(x => x.Id == 222));
        }