2012-06-26 1 views
2

См этого кода:сгенерированный сервисный макет: все, кроме RhinoMocks, не удается?

TicketStoreService fakeTicketStoreService = 
             MockRepository.GenerateMock<TicketStoreService>(); 

fakeTicketStoreService.Expect(service => service.DoSomething(Arg.Is(new Guid())) 
         .Return(new Guid()); 

fakeTicketStoreService.DoSomething(Arg.Is(new Guid())); 
fakeTicketStoreService.VerifyAllExpectations(); 

Заметьте, что DoSomething не является виртуальным methodcall в сгенерированном классе, который наследует от NO интерфейса. Так что это не должно работать, в соответствии с общеизвестными. Но это так.

Проблема заключается в том, что это единственный (некоммерческое) рамки, которые могут сделать это:

  • Rhino.Mocks работает, и проверка работы тоже
  • FakeItEasy говорит, что не находит конструктор по умолчанию (вероятно, просто неправильное сообщение исключение): No default constructor was found on the type SomeNamespace.TicketStoreService
  • Moq дает что-то в здравом уме и понятно: Invalid setup on a non-virtual (overridable in VB) member: service=> service.DoSomething
  • Nsubstitute дает сообщение System.NotSupportedException: Cannot serialize member System.ComponentModel.Component.Site of type System.ComponentModel.ISite because it is an interface.

Мне действительно интересно, что здесь происходит с каркасами, кроме Moq. «Причудливые новые» рамки, похоже, также имеют начальный перфоманс, возможно, готовят кеширование типов и сериализуют материал, в то время как RhinoMocks каким-то образом удается создать очень «тонкий» макет без рекурсии. Я должен признать, что мне очень не нравилось RhinoMocks, но здесь оно сияет .. к сожалению.

Итак, есть ли способ получить это для работы с новыми (некоммерческими!) Фальшивыми фреймворками или каким-то образом получить разумное сообщение об ошибке (описывающее, какой из 6 параметров, которые я фактически использовал, различен, каким образом) из Rhino.Mocks? И почему Rhino.Mocks достигают этого, когда ясно, что каждая среда Mocking утверждает, что она может работать только с виртуальными методами, когда задан конкретный класс?

* Давайте не сорвать обсуждение, говорить об альтернативных подходах, таких как экстракт & Override или во время выполнения прокси структур Mocking как JustMock/TypeMock/Родинка или новая Подделка рамка, я знаю, что это, но это было бы менее идеальным решение, по причинам, выходящим за рамки этой темы.

+0

MockRepository возвращает Mock ? в случае Moq? – Anton

+0

@ Anton no, Mock , потому что TicketStoreService - это сгенерированная служба, не получающая от интерфейса. Поведение макета понятно, проблема в том, почему RhinoMocks работает и почему другие структуры не могут это сделать? – hko

ответ

4

Вы можете попробовать плагин Fody Virtuosity, который делает все члены виртуальными, используя il weaving, поэтому любая динамическая прокси-библиотека сможет работать с ним. Проверьте Fody example на то, что связано с этим.

Как почему Rhino Mocks работает, я не мог заставить его:

[Test] 
public void FieldTest() { 
    var fakeTicketStoreService = MockRepository.GenerateMock<TicketStoreService>(); 
    fakeTicketStoreService.Expect(service => service.DoSomething(Arg.Is(new Guid()))).Return(new Guid()); 
    fakeTicketStoreService.DoSomething(Arg.Is(new Guid())); 
    fakeTicketStoreService.VerifyAllExpectations(); 
} 

public class TicketStoreService { 
    public Guid DoSomething(Guid guid) { return guid; } 
} 

Он терпит неудачу с:

System.InvalidOperationException : Invalid call, the last call has been used or no call has been made (make sure that you are calling a virtual (C#)/Overridable (VB) method). 
    at Rhino.Mocks.LastCall.GetOptions() 
    at Rhino.Mocks.RhinoMocksExtensions.Expect(T mock, Function`2 action) 

Похоже, что есть что-то еще происходит здесь. Можете ли вы опубликовать отдельный, минимальный случай, который воспроизводит это?

Наконец, все библиотеки, о которых вы упомянули, являются с открытым исходным кодом, поэтому было бы здорово выбрать тот, который вам больше всего нравится, и посмотреть, можете ли вы улучшить сообщения об ошибках или производительность. Если вы не внесли свой вклад в открытый исходный код, прежде чем он может показаться немного сложным, но люди из проектов, как правило, слишком счастливы, чтобы попытаться помочь кому-либо интересному вносить свой вклад.:)

+0

Хороший ответ, к сожалению, я не могу отметить это как правильно сейчас, потому что он не отвечает на вопрос, почему RhinoMocks работает там, но Fody кажется настолько хорошим, что я не думаю, что нашел здесь что-то новое. Я работал над проблемой с помощью обертки, которая инкапсулировала вызовы служб, в любом случае, очистила (сообщения об ошибках NSubstitute) сообщения об ошибках RhinoMocks), но, конечно, +1 для этого и принял ответ после того, как я уверен, что никто больше не прыгает;) – hko

+0

Я рад понять, почему Rhino Mocks работает для вашего дела, но вам нужно опубликовать runnable пример, потому что я не могу воспроизвести его. :) –

+0

Я постараюсь сделать это, когда я получу время, сам класс обслуживания, к сожалению, является очень большим, частичным классом, поэтому мне пришлось постепенно стирать его ... снова, сделаю это, как только найду время. :) – hko

Смежные вопросы