2014-10-12 1 views
3

У меня проблема с издевательским интерфейсом с методом (async). Интерфейс выглядит следующим образом:FakeItEasy выбрасывает ExpectationException

public interface IDataAccessLayer 
    { 
     Task<bool> ExistsUserAsync(string username, CancellationToken cancellationToken); 

     Task<IUser> CreateUserAsync(string username, string password, DateTime dateOfBirth, CancellationToken cancellationToken); 
    } 

.. параметр CancellationToken там всегда создается и передается извне во время выполнения (через NancyFx), и когда насмешливый звонки внутри метода испытаний, как это:

var validSignupRequest = new UserSignupRequest() 
    { 
     Username = "meh-spacey_space", 
     DateOfBirth = DateTime.Now.Subtract(TimeSpan.FromDays(365*35)), 
     Password = "someproper_passw*rd" 
    }; 

    var testDataAccessLayer = A.Fake<IDataAccessLayer>(options => options.Strict()); 

    var fakeUserInstance = A.Fake<IUser>(); 

    A.CallTo(() => fakeUserInstance.Username).Returns(validSignupRequest.Username); 
    A.CallTo(() => testDataAccessLayer.ExistsUserAsync(validSignupRequest.Username, CancellationToken.None)).Returns(false); // works 
    A.CallTo(() => testDataAccessLayer.CreateUserAsync(validSignupRequest.Username, validSignupRequest.Password, validSignupRequest.DateOfBirth, CancellationToken.None)).Returns(fakeUserInstance); // does not work/throws ExpectationException 

.. издевались вызов .ExistsUserAsync (...) работает, то .CreateUserAsync один делает не работа/бросает ExpectationException.

Я проверил базовый код, который тестируется, и вызов выполняется с использованием тех же значений для метода .CreateUserAsync (...) & Я подозревал, что dateOfBirth является виновником, но, по крайней мере. Клещи мудрые, это точно то же самое.

Я немного сомневаюсь в том, как FakeItEasy выполняет согласование подписи/параметра, потому что теоретически, что вызов IS издевается, но FakeItEasy говорит, что это не так. Пока это выигрыш.

Кто-нибудь знает, что не так в моем методе насмешливых звонков?

+0

Я специально установил .Strict(), чтобы увидеть, что/что-то происходит здесь. –

+0

Возможно, мне что-то не хватает, но я скопировал ваш образец кода в решение, добавил определения заглушки для 'IUser' и' UserSignupRequest', и мой тест проходит. Конечно, у меня есть столько же кода, сколько вы вставили, до 'A.CallTo (() => testDataAccessLayer.CreateUserAsync ...)'. (Я положил его в https://gist.github.com/blairconrad/a8f90d9d8ea04cee5e84) Вы говорите, что 'A.CallTo' терпит неудачу? Или что есть некоторый тестовый код, который у вас есть после третьего «A.CallTo», который терпит неудачу? Если последний, пожалуйста, включите его. Если первое, вы можете вставить полное исключение, которое повышает FakeItEasy? –

+0

Блэр, самый последний A.CallTo терпит неудачу, да с вышеупомянутым ExpectationException (метод .CreateUserAsync упоминается в сообщении исключения). Я далеко от машины, я расскажу подробнее подробнее) –

ответ

0

Для того, чтобы иметь «ответ» на этот вопрос, так новички не должны проходить через комментарии и гов и этажерки, чтобы понять вещи, вот мое понимание того, что произошло:

В изначальном вопросе вызов

A.CallTo(() => testDataAccessLayer.CreateUserAsync(
         validSignupRequest.Username, 
         validSignupRequest.Password, 
         validSignupRequest.DateOfBirth, 
         CancellationToken.None)) 
       .Returns(fakeUserInstance); 

не бросает, но позже, когда коды производства осуществлялись и testDataAccessLayer называли, настроенный метод не был выполнен-FakeItEasy не думает, что вызов соответствует то, что было настроен. не

Это происходит потому, что между настройкой вызова и фактический вызов, DateOfBirth заканчивал тем, что сериализации и десериализации по Jil, как показано на this gist и DateTime теряет точность, поэтому параметр больше не то же самое. Таким образом, FakeItEasy не видит необходимости перехватывать вызов.

Как отмечает Йорг Б., в комментариях не было проблем с FakeItEasy. Он делал все возможное с данными, которые он дал.

+1

Точно, спасибо Блэр за резюме! –

0

Это просто предположение, поскольку я не знаком с FakeItEasy, но, возможно, вам нужно ждать результатов асинхронных вызовов.

A.CallTo(async() => await testDataAccessLayer.CreateUserAsync( // await the result 
        validSignupRequest.Username, validSignupRequest.Password, validSignupRequest.DateOfBirth, CancellationToken.None)) 
    .Returns(fakeUserInstance); 

Или, в зависимости от того, как FakeItEasy работает внутри, это может быть в том, как вы проверить результат:

A.CallTo(() => testDataAccessLayer.CreateUserAsync(
       validSignupRequest.Username, validSignupRequest.Password, validSignupRequest.DateOfBirth, CancellationToken.None)) 
    .Returns(Task.FromResult(fakeUserInstance)); // test a task, not a real object 

Быстрый поиск нашел this page, который наклоняется ко второму решению, но я думаю, что либо вероятно, будет работать.

+0

спасибо за подсказку, однако я забыл упомянуть там, что я уже пытался это раньше (Task.FromResult (..), так как именно изначально у меня были все тесты на основе асинхронных/целевых задач). Но в этом случае это ничего не помогло и не изменило. FakeItEasy даже не добирается до части .Returns (..), поскольку, как представляется, он не может «найти» мою издеваемую подпись в первую очередь. –

+1

Должно быть ясно, что метод async возвращает задачу , и поэтому ваша настройка FakeItEasy также должна возвращать задачу , а не что-то. Task.FromResult() - это путь. Кроме того, вы не показываете, как вы называете фальшивые методы, поэтому вам трудно помочь. Вики FakeItEasy специально охватывают асинхронные методы: https://github.com/FakeItEasy/FakeItEasy/wiki/Faking-async-methods –

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