namespace TestProject1
{
    using System;
    using System.Linq.Expressions;
    using MongoDB.Driver;
    using Moq;

    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
            var prop = BuildPropAccessor<DateTime?>(nameof(ChildBaseClass.Timestamp));
            var dateTimeNow = DateTime.UtcNow;
            var filter = Builders<ParentClass>.Filter.Eq(x => x.Child.Timestamp, null);
            var update = Builders<ParentClass>.Update.Set(prop, dateTimeNow);
            var update2 = Builders<ParentClass>.Update.Set(x => x.Child.Timestamp, dateTimeNow);
            var mockCOllection = new Mock<ITestCollection>(MockBehavior.Strict);
            mockCOllection.Setup(x => x.UpdateProperty(
            It.Is<UpdateDefinition<ParentClass>>(x => x.UpdateDefinitionEquals(update)),
            It.Is<FilterDefinition<ParentClass>>(x => x.FilterDefinitionEquals(filter))));

            var testObj = new TestClass(mockCOllection.Object);
            testObj.CallUpdate(update, filter);
        }

        protected Expression<Func<ParentClass, TPROP>> BuildPropAccessor<TPROP>(string propName)
        {
            var param = Expression.Parameter(typeof(ParentClass));
            var body = Expression.ConvertChecked(Expression.Property(Expression.Property(param, nameof(ParentClass.Child)), propName), typeof(TPROP));
            var prop = Expression.Lambda<Func<ParentClass, TPROP>>(body, param);
            return prop;
        }

        private class TestClass
        {
            private ITestCollection _testCollection;

            public TestClass(ITestCollection testCollection)
            {
                _testCollection = testCollection;
            }

            public void CallUpdate(UpdateDefinition<ParentClass> update, FilterDefinition<ParentClass> filter)
            {
                _testCollection.UpdateProperty(update, filter);
            }
        }
    }
}