Как вернуть DispatcherOperation из издевательского объекта

#c# #wpf #nunit #moq

#c# #wpf #nunit #moq

Вопрос:

У меня есть метод, который возвращает DispatcherOperation<TResult> объект:

 public DispatcherOperation<TResult> InvokeAsync<TResult>(Func<TResult> callback)
{
    return this.UIDispatcher.InvokeAsync(callback);
}
 

Как он используется в приложении:

 var res = await this.dispatcher.InvokeAsync(() =>
                                             {
                                                // returns a List<string> by computing some logic
                                             });
 

И я издевался над этим методом, используя moq:

 this.mockDispatcher.Setup(x => x.InvokeAsync(It.IsAny<Func<List<string>>())).Callback((Func<List<string>> callback) => callback.Invoke());
 

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

Я знаю, что обратный вызов не следует использовать для возврата значений, но я не могу определить метод возврата, который может возвращать результат типа DispatcherOperation<T>

Вот что я пытаюсь:

 this.mockDispatcher.Setup(x => x.InvokeAsync(It.IsAny<Func<List<string>>>())).Returns((Func<List<string>> callback) => callback()));
 

Как мне вернуть его как DispatcherOperation<List<string>>

Комментарии:

1. Вам не нужно звонить callback ? .Returns(callback => callback())

2. @AluanHaddad Я отредактировал вопрос с правильным синтаксисом, меня беспокоит, что он возвращается List<string> туда, где мне нужно DispatcherOperation<List<string>>

3. Я вижу. Я не думаю, что вы можете, потому что конструктор DispatcherOperation<TResult> является внутренним.

4. @AluanHaddad итак, вы говорите, что нет другого способа высмеять это, кроме как вернуть измененный результат? подождите, даже это невозможно, не так ли

5. К сожалению, нет.

Ответ №1:

Вы можете Task<T> довольно легко издеваться над:

 public Task<TResult> InvokeAsync<TResult>(Func<TResult> callback)
{
    return this.UIDispatcher.InvokeAsync(callback).Task;
}
 
 this.mockDispatcher.Setup(x => x.InvokeAsync(It.IsAny<Func<List<string>>())).Callback((Func<List<string>> callback) => Task.FromResult(callback.Invoke()));
 

Гораздо проще издеваться над типом общего назначения, подобным Task<T> , а не над типом, специфичным для фреймворка DispatcherOperation<TResult> . Однако, если вы должны использовать DispatcherOperation<TResult> , у вас также есть возможность создать тестовый Dispatcher экземпляр (и выполнить всю перекачку сообщений и все необходимое с помощью гораздо более тяжелого макета, подобного этому).

Комментарии:

1. вы пропустили > , кроме того, что это сработало как шарм, я не знал, что вы можете реализовать это таким образом, это было именно то, что мне было нужно.

2. Единственная проблема заключается в том, почему я не могу сделать его универсальным, например It.IsAny<Func<It.IsAnyType>> , вместо того, чтобы привязывать его к типу параметра метода.

3. @ThePiatre: я не очень хорошо знаком с такого рода плавным издевательством, поэтому я не знаю, есть ли способ заставить это работать.