Exception when unit testing code where the Future method is used
When I execute a unit test on code that uses the Future() method it will throw an exception:
Oops! A general error has occurred. Please report the issue including the stack trace to our support team: [email protected]
at Z.EntityFramework.Plus.InternalExtensions.GetObjectQuery[T](IQueryable
1 query) at Z.EntityFramework.Plus.QueryFutureExtensions.Future[T](IQueryable1 query) at Domain.Service.GlobalSearchService.<Search>d__5.MoveNext() in D:\Projects\Main\Projects\Domain\Service\GlobalSearchService.cs:line 30
There is solution for EntityFramework.Extended. You can found it here: https://github.com/zzzprojects/EntityFramework.Extended/issues/129 However, approach of wrapping Future() method is not achievable with EntityFramework-Plus. ToObjectQuery method is internal now. Why it is so?
Hello @tomaspakala ,
EntityFramework.Extended and EntityFramework.Plus is not the same library, so that's normal there is some difference.
When the V2 will be under development, we will make sure to try to release some utilities like this one method public.
Best Regards,
Jonathan
@JonathanMagnan are there any updates about making the utility method GetObjectQuery() public?
Hello @aschiffmann ,
We will look this week if there is any reason why we don't want this method public yet!
In 1-2 months, we will more globally check which helper method should be made public in https://entityframework-classic.net/, then we will probably make the same change in this library.
Hello @aschiffmann ,
The v1.8.25 has been released
The extension methods GetObjectQuery is now public. We are not ready yet to make a utilities section for EF Classic, so we choose to just make it public here meanwhile.
@aschiffmann @JonathanMagnan Something i came up with last month after an epiphany. It will allow you to mock a Future object for return from a mocked repository call.
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Z.EntityFramework.Plus;
namespace TestFutureHelper
{
public static class TestFutureHelper<T> where T : class
{
public static QueryFutureValue<T> GetFutureValue(T data)
{
var context = GetInMemoryDbContext<TestContext<T>>();
context.Add(data);
context.SaveChanges();
return context.TestData.FutureValue();
}
public static QueryFutureEnumerable<T> GetFutureEnumerable(IEnumerable<T> data)
{
var context = GetInMemoryDbContext<TestContext<T>>();
context.AddRange(data);
context.SaveChanges();
return context.TestData.Future();
}
private static TContext GetInMemoryDbContext<TContext>() where TContext : DbContext
{
var optionsBuilder = new DbContextOptionsBuilder<TContext>();
var guid = Guid.NewGuid().ToString();
optionsBuilder.UseInMemoryDatabase(databaseName: guid)
.ConfigureWarnings(w => w.Ignore(Microsoft.EntityFrameworkCore.Diagnostics.InMemoryEventId.TransactionIgnoredWarning))
.EnableSensitiveDataLogging();
var context = (TContext)Activator.CreateInstance(typeof(TContext), optionsBuilder.Options);
BatchDeleteManager.InMemoryDbContextFactory = () => context;
BatchUpdateManager.InMemoryDbContextFactory = () => context;
return context;
}
private class TestContext<T> : DbContext where T : class
{
public TestContext(DbContextOptions<TestContext<T>> options) : base(options)
{
}
public DbSet<T> TestData { get; set; }
}
}
}
unit tests
[Test]
public void TestFutureValue()
{
var expected = new TestObject();
QueryFutureValue<TestObject> value = null;
Assert.DoesNotThrow(() => value = TestFutureHelper<TestObject>.GetFutureValue(expected));
Assert.IsNotNull(value);
TestObject ret = null;
Assert.DoesNotThrow(() => ret= value.Value);
Assert.AreEqual(expected, ret);
}
[Test]
public void TestFutureEnumerable()
{
var expected = new TestObject();
QueryFutureEnumerable<TestObject> enumerable = null;
Assert.DoesNotThrow(() => enumerable = TestFutureHelper<TestObject>.GetFutureEnumerable(new List<TestObject>{expected}));
Assert.IsNotNull(enumerable);
List<TestObject> ret = null;
Assert.DoesNotThrow(() => ret = enumerable.ToList());
Assert.AreEqual(expected, ret[0]);
}
private class TestObject
{
[Key]
public int Id { get; set; }
public string Test { get; set; }
}
@JonathanMagnan I' trying to mock QueryFutureEnumerable object with autofixture something like var foo = fixture.Create<QueryFutureEnumerable<long>>() ,
But I'm getting the following error,
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
System.ArgumentException: Format of the initialization string does not conform to specification starting at index 0.