伪造/模拟接口给出“没有默认构造函数”错误,怎么会这样?

我正在尝试编写存储库实现的unit testing。 存储库使用RavenDB作为数据库。 对于unit testing,我想模拟RavenDB部分。 为了创造嘲笑(假货)我正在使用FakeItEasy。 我认为由于RavenDB API是通过接口访问的,因此模拟/伪装不会有任何问题。

但是,在尝试实例化特定模拟时,我确实遇到了问题。 我的unit testing代码的相关部分如下所示:

[Fact] public void Test() { UserDocument doc = ...; IQueryable where = A.Fake<IQueryable>(); A.CallTo(() => where.First()).Returns(doc); IRavenQueryable query = A.Fake<IRavenQueryable>(); IDocumentSession session = A.Fake(); A.CallTo(() => session.Query()).Returns(query); IDocumentStore store = A.Fake(); A.CallTo(() => store.OpenSession()).Returns(session); . . . } 

在实例化IRavenQueryable假的时候,我得到了一个exception。 这是来自Xunit.net跑步者的日志:

 UnitTest.Test : FakeItEasy.Core.FakeCreationException : Failed to create fake of type "System.Linq.IQueryable`1[UserDocument]". Below is a list of reasons for failure per attempted constructor: No constructor arguments failed: No default constructor was found on the type System.Linq.IQueryable`1[UserDocument]. Stack Trace: vid FakeItEasy.Core.DefaultExceptionThrower.ThrowFailedToGenerateProxyWithResolvedConstructors(Type typeOfFake, String reasonForFailureOfUnspecifiedConstructor, IEnumerable`1 resolvedConstructors) vid FakeItEasy.Creation.FakeObjectCreator.TryCreateFakeWithDummyArgumentsForConstructor(Type typeOfFake, FakeOptions fakeOptions, IDummyValueCreationSession session, String failReasonForDefaultConstructor, Boolean throwOnFailure) vid FakeItEasy.Creation.FakeObjectCreator.CreateFake(Type typeOfFake, FakeOptions fakeOptions, IDummyValueCreationSession session, Boolean throwOnFailure) vid FakeItEasy.Creation.DefaultFakeAndDummyManager.CreateFake(Type typeOfFake, FakeOptions options) vid FakeItEasy.Creation.DefaultFakeCreatorFacade.CreateFake[T](Action`1 options) 

“没有找到默认构造函数”没有任何意义,因为我想要伪造的是一个接口。 有没有人建议问题可能是什么?

你是正确的,因为exception消息没有任何意义,这是一个错误。 如果你能提供一个VS-solution来重现bug并在这里提出问题,那将是很棒的: https : //github.com/patrik-hagne/FakeItEasy/

错误在于使用了错误的exception消息,但是必定存在错误导致虚假创建出错。 “UserDocument”类型是公共的吗? 如果它是内部的,并且您已通过使用InternalsVisibleToAttribute给予测试项目访问权限,那么您还必须让代理生成库访问它: https : //github.com/FakeItEasy/FakeItEasy/wiki/How-to -fake-internal-(Friend-in-VB)-types 。

IRavenQueryable接口是否具有where T : new() 类型约束 ?

如果是这样,并且UserDocument没有提供无参数的ctor,这可能会导致您的问题。

我刚碰到这个,但我的问题不在于内部类型。 我的问题是包含不在unit testing项目的bin文件夹中的类型的程序集。

当FakeItEasy无法解析它需要伪造的类型时,它似乎会抛出此错误。 (这是有道理的,为什么另一个程序集中的内部类型会导致相同的错误。)

所以,我有Project Foo,Project Bar引用了它。 Project Bar有一个公共接口,引用Project Foo的公共类型。 Project Bar.Tests引用Project Bar,但不是Project Foo。 当我构建Bar.Tests时,Bar.dll被放入bin文件夹但Foo.dll没有。 当FakeItEasy试图伪造我的界面时,它无法解析驻留在Foo.dll中的类型。

在我的Bar.Tests项目中添加对Project Foo的引用确保Foo.dll完成并且FakeItEasy存在,并使此错误消失。

所以…

在您的情况下,可能是您的RavenDB程序集(我假设包含UserDocument )仅由您的实际项目引用,并且不会被复制到您的unit testing构建输出。

我知道这是一个老post,但我遇到了同样的问题。 我发现的问题是我试图伪造的界面中声明的方法之一的返回类型。 这个方法返回了某个类的对象,而且这个类没有FakeItEasy可以使用的默认构造函数。 如果其他人收到此错误,请尝试检查接口返回的对象,以及相应的类是否具有默认构造函数。