2017-10-15 41 views
3

我正在努力通过编写一些可以为我创建属性的助手来使EF更容易进行单元测试。我有一对夫妇的支持领域打开带有通用返回类型的类型

private Mock<DbSet<Workflow>> mockedWorkFlows; 
private Mock<DbSet<WorkflowError>> mockedWorkFlowErrors; 

而且我希望有一个通用的功能,能够回到我正确的支持字段具有以下功能

public Mock<DbSet<T>> Mocked<T>(T t) where T : class 
{ 
    if ((object)t is Workflow) 
    { 
     return mockedWorkFlows; //cannot Workflow to T 
    } 
} 

有,我想一些私人支持字段根据传递的类型返回。

但是,即使我添加了类别约束Workflow,我也会得到相同的错误。

我也尝试切换t's类型,但没有运气。几个后备字段的类型不共享除对象以外的共同祖先。我正在尝试做什么?

+0

我没有看到这个方法的重点。创建一个模拟需要1行代码,如果你想设置模拟,你必须单独设置每一个模拟,所以你为什么不创建一个工厂模拟某些类型。 – FCin

+0

从你的EF上下文中嘲笑一个IDbSet 不止一行代码。我有一个流畅的接口来分配数据,但是你必须在某个地方公开后台字段,因为当你窥探那些实际上被调用的时候。我只想要一个较小的API,而不是为上下文的所有IDbSet属性设置WorkflowsMo​​cked,WorkflowErrorsMocked等。 – wootscootinboogie

+0

而不是模拟'DbSet',你有没有考虑嘲笑'SqlConnection',例如,使用Effort框架? https://github.com/tamasflamich/effort –

回答

6

如果我正确理解你的意图 - 你可以做这样的:

// no need to pass instance of T - why? 
public Mock<DbSet<T>> Mocked<T>() where T : class 
{ 
    if (typeof(T) == typeof(Workflow)) { 
     // first cast to object, then to return type to avoid compile error 
     // compiler does not know mockedWorkFlows is Mock<DbSet<T>>, but you 
     // know it already, because you checked type 'T' 
     return (Mock<DbSet<T>>) (object) mockedWorkFlows; //cannot Workflow to T 
    } 
    // etc 
    return null; 
} 

无论是好主意与否是一个不同的故事。

+0

这就是我正在寻找的。我正在尝试使用C#7类型的开关,但最终我正在寻找(尽管现在我得到了一个不同的错误!:)) – wootscootinboogie

1

有可能与when警卫严重滥用C#7的switch达到你想要的东西通过一个无关值切换并使用var模式:

public Mock<DbSet<T>> Mocked<T>() where T : class 
{ 
    switch(true) 
    { 
     case var _ when typeof(T) == typeof(Workflow): 
      return ... 
     case var _ when typeof(T) == typeof(WorkflowError): 
      return ... 
     default: 
      return null; 
    } 
} 

但它的真正可怕的代码,所以请不要不要这样做!

能够匹配switch语句中的类型是一个非常普遍的要求。有关于在github上正式语言回购的C#改进建议(请参阅Proposal: switch on System.Type和p Proposal: Pattern match via generic constraint)。当更多的模式匹配功能被添加到C#(currently, set for "a 7.X release")时,我们可能会获得更好的语法来实现此功能。