Подделка / насмешка над интерфейсом выдает ошибку «нет конструктора по умолчанию», как это может быть? - PullRequest
7 голосов
/ 26 сентября 2011

Я пытаюсь написать модульный тест реализации репозитория.Репозиторий использует RavenDB в качестве базы данных.Для модульных тестов я хотел бы издеваться над деталями RavenDB.Для создания макетов (подделок) я использую FakeItEasy.Я полагал, что не будет никаких проблем с подделкой / подделкой, так как API RavenDB доступен через интерфейсы.

У меня, однако, есть проблема при попытке создать конкретную модель.Соответствующие части кода моего модульного теста выглядят следующим образом:

[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 ]

6 голосов
/ 02 октября 2011

Вы правы в том, что сообщение об исключении не имеет никакого смысла, это ошибка.Было бы здорово, если бы вы могли предоставить VS-решение, которое воспроизводит ошибку, и сообщить о проблеме здесь: https://github.com/patrik-hagne/FakeItEasy/

Ошибка заключается в том, что используется неправильное сообщение об исключении, однако должно быть что-то неправильное, чтоделает ложное создание не так.Является ли тип UserDocument общедоступным?Если он является внутренним, и вы предоставили ему доступ к своему тестовому проекту с помощью InternalsVisibleToAttribute, вы также должны предоставить доступ к нему для библиотеки, генерирующей прокси: https://github.com/FakeItEasy/FakeItEasy/wiki/How-to-fake-internal-(Friend-in-VB)-types.

2 голосов
/ 13 октября 2011

Я только что столкнулся с этим, но моя проблема не была связана с внутренними типами. Моя проблема была со сборкой, содержащей тип, которого нет в папке 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.

Добавление ссылки на Project Foo в мой проект Bar.Tests гарантировало, что Foo.dll завершит работу и существует для FakeItEasy, и заставило эту ошибку исчезнуть.

Итак ...

В вашем случае может случиться так, что на вашу сборку RavenDB (которая, как я предполагаю, содержит UserDocument) ссылается только ваш реальный проект, и она не копируется в выходные данные сборки модульного теста.

2 голосов
/ 26 сентября 2011

Имеет ли интерфейс IRavenQueryable<T> ограничение типа where T : new() ?

Если это так, и UserDocument не предоставляет ctor без параметров, это может быть причиной вашей проблемы.

1 голос
/ 25 октября 2012

Я знаю, что это старый пост, но я столкнулся с той же проблемой. Я обнаружил, что проблема заключается в типе возврата одного из методов, объявленных в интерфейсе, который я пытался подделать. Этот метод возвращал объект определенного класса, и у этого класса не было конструктора по умолчанию, с которым мог бы работать FakeItEasy. Если кто-то еще получает эту ошибку, попробуйте проверить объекты, которые возвращает ваш интерфейс, и если соответствующие классы имеют конструкторы по умолчанию.

...