gpt4 book ai didi

c# - 如何对包含 EntityFunctions.AddDays 函数的 GetNewValues() 进行单元测试

转载 作者:行者123 更新时间:2023-12-02 19:36:54 26 4
gpt4 key购买 nike

Below sample code is working fine in production, but cannot be unit tested because the EntityFunctions.

my unit test project is using InMemoryDatabase instead of real SQL database. I can easily solve my problem by creating a View in SQL database with computed column myValue and newValue. I like to find a way to do the unit test work without changing my method and without creating new SQL view

<小时/>
public class EcaseReferralCaseRepository : Repository
{

public class myType
{
public DateTime myValue;
public DateTime newValue;
}

public myType GetNewValues()
{
return
(myType)(from o in context.EcaseReferralCases
select new myType
{
// LINQ to Entity
myValue = (DateTime)System.Data.Objects.EntityFunctions.AddDays(o.StartDate, 0),
newValue = (DateTime)System.Data.Objects.EntityFunctions.AddDays(o.StartDate, 30)

// LINQ to Object
//myValue = o.StartDate.AddDays(0),
//newValue = o.StartDate.AddDays(30)

});
}
}
<小时/>

This link shows a good example to unit test EntityFunctions ,我用这种方法解决了我的一个单元测试难题,但不知道如何解决这个问题。

最佳答案

除非我弄错了,否则您将使用另一个 IQueryable(可能是 LINQ To Objects 可查询源)来切换 EcaseReferralCases 的实现。

最可靠的方法可能是使用表达式访问器将对 EntityFunctions 的调用替换为您自己的 L2Objects 兼容函数。

这是我的实现:

using System;
using System.Data.Objects;
using System.Linq;
using System.Linq.Expressions;

static class EntityFunctionsFake
{
public static DateTime? AddDays(DateTime? original, int? numberOfDays)
{
if (!original.HasValue || !numberOfDays.HasValue)
{
return null;
}
return original.Value.AddDays(numberOfDays.Value);
}
}
public class EntityFunctionsFakerVisitor : ExpressionVisitor
{
protected override Expression VisitMethodCall(MethodCallExpression node)
{
if (node.Method.DeclaringType == typeof(EntityFunctions))
{
var visitedArguments = Visit(node.Arguments).ToArray();
return Expression.Call(typeof(EntityFunctionsFake), node.Method.Name, node.Method.GetGenericArguments(), visitedArguments);
}

return base.VisitMethodCall(node);
}
}
class VisitedQueryProvider<TVisitor> : IQueryProvider
where TVisitor : ExpressionVisitor, new()
{
private readonly IQueryProvider _underlyingQueryProvider;
public VisitedQueryProvider(IQueryProvider underlyingQueryProvider)
{
if (underlyingQueryProvider == null) throw new ArgumentNullException();
_underlyingQueryProvider = underlyingQueryProvider;
}

private static Expression Visit(Expression expression)
{
return new TVisitor().Visit(expression);
}

public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
{
return new VisitedQueryable<TElement, TVisitor>(_underlyingQueryProvider.CreateQuery<TElement>(Visit(expression)));
}

public IQueryable CreateQuery(Expression expression)
{
var sourceQueryable = _underlyingQueryProvider.CreateQuery(Visit(expression));
var visitedQueryableType = typeof(VisitedQueryable<,>).MakeGenericType(
sourceQueryable.ElementType,
typeof(TVisitor)
);

return (IQueryable)Activator.CreateInstance(visitedQueryableType, sourceQueryable);
}

public TResult Execute<TResult>(Expression expression)
{
return _underlyingQueryProvider.Execute<TResult>(Visit(expression));
}

public object Execute(Expression expression)
{
return _underlyingQueryProvider.Execute(Visit(expression));
}
}
public class VisitedQueryable<T, TExpressionVisitor> : IOrderedQueryable<T>
where TExpressionVisitor : ExpressionVisitor, new()
{
private readonly IQueryable<T> _underlyingQuery;
private readonly VisitedQueryProvider<TExpressionVisitor> _queryProviderWrapper;
public VisitedQueryable(IQueryable<T> underlyingQuery)
{
_underlyingQuery = underlyingQuery;
_queryProviderWrapper = new VisitedQueryProvider<TExpressionVisitor>(underlyingQuery.Provider);
}

public IEnumerator<T> GetEnumerator()
{
return _underlyingQuery.GetEnumerator();
}

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

public Expression Expression
{
get { return _underlyingQuery.Expression; }
}

public Type ElementType
{
get { return _underlyingQuery.ElementType; }
}

public IQueryProvider Provider
{
get { return _queryProviderWrapper; }
}
}

这是一个使用示例:

var linq2ObjectsSource = new List<DateTime?>() { null }.AsQueryable();
var visitedSource = new VisitedQueryable<DateTime?, EntityFunctionsFakerVisitor>(linq2ObjectsSource);
var visitedQuery = visitedSource.Select(dt => EntityFunctions.AddDays(dt, 1));
var results = visitedQuery.ToList();
Assert.AreEqual(1, results.Count);
Assert.AreEqual(null, results[0]);

通过这种方式,您可以获得所有理想的特征:

  • 开发者可以继续使用 Entity Framework 定义的标准EntityFunctions
  • 如果不在数据库上运行,生产实现仍保证会引发异常;
  • 可以针对虚假存储库测试查询;

关于c# - 如何对包含 EntityFunctions.AddDays 函数的 GetNewValues() 进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14883360/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com