Есть ли случаи, когда It.IsAny не соответствует значению? - PullRequest
0 голосов
/ 06 августа 2020

Я использую библиотеку Moq для имитации интерфейсов, предоставляемых библиотекой Prism в моем проекте MVVM WPF, чтобы протестировать их как часть моей модели просмотра. В частности, у меня есть модель просмотра, которая использует призмы IDialogService.

. Я хочу провести модульную проверку, открывает ли выполнение определенной команды c диалоговое окно c с указанными c параметрами. Вот что я сделал для этого:

 // Arrange

 var mockDialogService = new Mock<IDialogService>();
 var viewModel = SetupViewModel(mockDialogService.Object);

 // Act

 viewModel.OpenNewStockDialogueCommand.Execute();

 // Assert

 mockDialogService.Verify(s => s.ShowDialog(
   It.IsAny<string>(),
   It.IsAny<IDialogParameters>(),
   It.IsAny<Action<IDialogResult>>()),
   Times.Once);

Соответствующая часть происходит в разделе Assert моего теста. Метод ShowDialog принимает следующие аргументы:

  1. имя: string
  2. параметры: IDialogParameters
  3. обратный вызов: Action<IDialogResult>

Вот некоторая документация по Prism Dialogservice, для заинтересованных

Теперь, насколько я понимаю, если я вызову метод ShowDialog перед вызовом Метод Verify, независимо от того, какие параметры я ему передаю, метод Verify должен выполняться без исключения. Как вы, наверное, догадались, когда я был на форуме, на самом деле он вызывает исключение и представляет мне следующее сообщение:

Message: 
    Moq.MockException : 
    Expected invocation on the mock once, but was 0 times: s => s.ShowDialog(It.IsAny<string>(), It.IsAny<DialogParameters>(), It.IsAny<Action<IDialogResult>>())
    
    Performed invocations:
    
       Mock<IDialogService:1> (s):
    
          IDialogService.Show("NewStockDialogue", ?CurrentStock=FHAA.Stock, Action<IDialogResult>)

Итак, вы go. Для меня это очень странно. Кажется, что метод действительно вызывается, как указано в «Выполненном вызове», но что-то в параметрах не соответствует. Есть ли у кого-нибудь идея, почему?

Также важно отметить, что я на самом деле не хочу помещать здесь It.IsAny, у меня есть некоторые полуфиксированные значения, которые я хочу проверить, но поскольку это не так событие работает с It.IsAny, на что я надеюсь, что он будет работать с ограничениями.

Большое спасибо за ваше время, ваша помощь очень ценится!

EDIT

Оказывается, я на самом деле тестировал IDialogService.Show вместо ShowDialog. Это была проблема

dialogService.Show(DialogueNames.NewStock, parameters, OnNewStockDialogueClosed);

1 Ответ

1 голос
/ 07 августа 2020

Как уже указывал @Nkosi, вы вызываете метод Show, но проверяете, был ли вызван ShowDialog. Это четко указано в сообщении об ошибке. Решите, какой из них вы хотите использовать, и адаптируйте модель теста или просмотра.

Также важно отметить, что я на самом деле не хочу его помещать. Разумеется, здесь у меня есть несколько полуфиксированных значений Я хочу протестировать [...]

Вы можете проверить условия по параметрам с помощью It.Is<T>, а не It.IsAny<T>. Вам просто нужно передать Expression<Func<T, bool>>, которое является выражением предиката. Этот предикат проверяет корректность соответствующего параметра и возвращает результат как bool. Посмотрите на этот пример.

viewModel.ShowDialog("My dialog name", new DialogParameters {{"Key 1", "Value 1"}}, result => testInt = 32);

Я назвал это ShowDialog в модели представления. Я могу проверить, верны ли параметры вот так.

var expectedDialogParameters = new DialogParameters {{ "Key 1", "Value 1" }};
mockDialogService.Verify(s => s.ShowDialog(
   It.Is<string>(name => name == "My dialog name"),
   It.Is<DialogParameters>(dialogParameters => dialogParameters.SequenceEqual(expectedDialogParameters)),
   It.IsAny<Action<IDialogResult>>()),
   Times.Once);

Для имени диалогового окна я просто проверяю string равенство в лямбде. В качестве параметров диалога я использую экземпляр ожидаемых параметров диалога. Я сравниваю DialogParameters с SequenceEqual, потому что они реализованы как IEnumerable<KeyValuePair<string, object>>, то есть список пар ключ-значение. Я не могу использовать Equals, потому что он не переопределяется в DialogParameters и будет проверять только ссылочное равенство , что приведет к ошибке. Кроме того, используйте DialogParameters в It.Is. IDialogParameters - это просто интерфейс для DialogParameters, который не реализует IEnumerable<KeyValuePair<string, object>>, поэтому вы не сможете сравнивать с SequenceEqual. И последнее, но не менее важное: вы можете проверить действие результата диалога, но это может быть нелегко. Вместо этого вы можете проверить в своей модели представления, что изменилось из-за выполняемого действия.

...