Search code examples
c#entity-frameworktestingentity-framework-6entity-framework-extended

How to fake EntityFramework.Extended FutureQuery?


I'm looking to setup a fake repository.

public class FooRepo {

    public FutureFoo<Foo> GetById(int id) {

        var foo = new Foo();
        return new FutureValue(foo);
    }

    public FutureQuery<Foo> GetByCategory(int categoryId) {

        var foos = new[] { new Foo(), new Foo() new Foo() };

        return  //what goes here?
    }

}

The purpose of this is for writing data dependent tests while not depending on any database connectivity. This was really straightforward for the FutureValue<> type as it provides a constructor that accepts a direct object. However the constructor for FutureQuery<> takes the arguments IQueryable query, Action loadAction

Can i just ignore loadAction?

Such as: new FutureQuery<Foo>(foos.AsQueryable(), () => { });

Or what is the proper way to go about this?


Coerced solution:

(FutureQuery<Foo>) Activator.CreateInstance(typeof(FutureQuery<Foo>),
                   BindingFlags.NonPublic | BindingFlags.Instance, null, 
                   new object[] { foos.AsQueryable(), null }, null);

Solution

  • Taken from FutureQueryBase.GetResult() :

        /// <summary>
        /// Gets the result by invoking the <see cref="LoadAction"/> if not already loaded.
        /// </summary>
        /// <returns>
        /// An <see cref="T:System.Collections.Generic.IEnumerable`1"/> that can be used to iterate through the collection.
        /// </returns>
        protected virtual IEnumerable<T> GetResult()
        {
            if (IsLoaded)
                return _result;
    
            // no load action, run query directly
            if (LoadAction == null)
            {
                _isLoaded = true;
                _result = _query as IEnumerable<T>;
                return _result;
            }
    
            // invoke the load action on the datacontext
            // result will be set with a callback to SetResult
            LoadAction.Invoke();
            return _result ?? Enumerable.Empty<T>();
        }
    

    You should pass a null for the load action, unless you want to explicitly update _result through SetResult(ObjectContext, DbDataReader).