9

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

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

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

当实例化 IRavenQueryable 假我得到一个异常。这是来自 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)

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

4

4 回答 4

11

您是正确的,异常消息没有任何意义,这是一个错误。如果您可以提供一个重现错误并在此处提交问题的 VS 解决方案,那就太好了:https ://github.com/patrik-hagne/FakeItEasy/

错误在于使用了错误的异常消息,但是肯定有一些错误导致伪造的创建出错。“UserDocument”类型是公开的吗?如果它是内部的,并且您已通过使用 InternalsVisibleToAttribute 授予您的测试项目访问权限,您还必须授予代理生成库访问权限:https ://fakeiteasy.readthedocs.io/en/stable/how-to -fake-internal-types/#how-to-fake-internal-friend-in-vb-types

于 2011-10-02T16:36:05.790 回答
3

I know it is an old post, but I ran into the same issue. What I found to be the problem was a return type of one of the methods declared into the interface I was trying to fake. This method was returning an object of a certain class, and this class didn't have a default constructor with which FakeItEasy could work. If someone else gets this error try to check the objects your interface is returning, and if the corresponding classes have the default constructors.

于 2012-10-25T07:45:19.473 回答
2

接口是否IRavenQueryable<T>where T : new() 类型约束

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

于 2011-09-26T18:19:27.930 回答
2

我刚遇到这个,但我的问题不在于内部类型。我的问题是包含类型的程序集不在单元测试项目的 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 项目中添加对项目 Foo 的引用可确保 Foo.dll 顺利通过并用于 FakeItEasy 并使此错误消失。

所以...

In your case, it could be that your RavenDB assembly (which I assume contains UserDocument) is only referenced by your actual project and is not getting copied to your unit test build output.

于 2011-10-12T21:37:12.300 回答