Moq-тесты с использованием ExpectSet () с It.Is <T>() не ведут себя как ... ожидается - PullRequest
0 голосов
/ 11 декабря 2008

Я выделил поведение в следующий тестовый пример. Я был бы благодарен любому, кто может сказать мне, как ожидать / проверить набор свойств для свойства List<T> - кажется, что внутри It.Is<T>(predicate) происходит что-то, что не имеет для меня сейчас большого смысла , Пример кода будет запущен как консольное приложение из VS2008 - вам нужно добавить ссылку на Moq 2.6 (я на 2.6.1014.1) - пожалуйста, попробуйте раскомментировать различные операторы ExpectSet, чтобы увидеть, что происходит ...

using System;
using Moq;
using System.Collections.Generic;

namespace MoqDemo {

    public interface IView {
        List<string> Names { get; set; }
    }

    public class Controller {
        private IView view;

        public Controller(IView view) {
            this.view = view;
        }

        public void PopulateView() {
            List<string> names = new List<string>() { "Hugh", "Pugh", "Barney McGrew" };
            view.Names = names;
        }

        public class MyApp {
            public static void Main() {
                Mock<IView> mockView = new Mock<IView>();

                // This works - and the expectation is verifiable.
                mockView.ExpectSet(mv => mv.Names);

                // None of the following can be verified.
                // mockView.ExpectSet(mv => mv.Names, It.Is<Object>(o => o != null));
                // mockView.ExpectSet(mv => mv.Names, It.Is<List<string>>(names => names.Count == 3));
                // mockView.ExpectSet(mv => mv.Names, It.IsAny<IList<String>>());

                Controller controller = new Controller(mockView.Object);
                controller.PopulateView();
                try {
                    mockView.VerifyAll();
                    Console.WriteLine("Verified OK!");
                } catch (MockException ex) {
                    Console.WriteLine("Verification failed!");
                    Console.WriteLine(ex.Message);
                }
                Console.ReadKey(false);
            }
        }
    }
}

Ответы [ 4 ]

1 голос
/ 04 января 2009

Кстати, это не поддерживается на ExpectSet. Ваш код компилируется только потому, что они являются регулярными вызовами методов, когда используются в качестве значений (в отличие от выражений), тогда как при использовании в Expect выражение они предварительно обрабатываются Moq и имеют конкретное значение (а не ноль). / значение по умолчанию, которое фактически возвращают все члены It.Is).

Вы можете использовать поведение заглушки в данном свойстве (mockView.Stub (mv => mv.Names)) и позднее утверждать его значение непосредственно после выполнения.

1 голос
/ 11 декабря 2008

Я не использую самую последнюю версию Moq, поэтому у меня нет перегрузки ExpectSet, которая принимает два параметра, но у меня был некоторый успех с этим шаблоном:

mockView.ExpectSet(mv => mv.Names).Callback(n => Assert.That(n != null));

Вызов Assert (из NUnit) в обратном вызове вызовет исключение, если значение, присвоенное .Names, не соответствует предикату. Тем не менее, его трудно отследить, когда тест не пройден. Я согласен, что возможность передавать It.Is или It.IsAny в качестве второго параметра была бы полезной.

1 голос
/ 11 декабря 2008

Второй параметр ExpectSet () - это ожидаемое вами значение. Вы не можете использовать It.Is<T> в этом случае, поскольку нет перегрузки, которая принимает предикат - хотя это было бы неплохо;) Вот (упрощенная) выдержка из вашего примера, иллюстрирующая использование значения:

var mockView = new Mock<IView>();
var list = new List<string> { "Hugh", "Pugh", "Barney McGrew" };

mockView.ExpectSet(mv => mv.Names, list);

mockView.Object.Names = list;

Надеюсь, это поможет.

Редактировать: исправлена ​​опечатка.

0 голосов
/ 04 января 2009

Moq не обеспечивает перегрузку при получении It.IsAny, так как он фактически аналогичен вызову ExpectSet без передачи ожидаемого значения;)

...