Почему moq утверждает, что метод установки свойств моего макета никогда не вызывается, даже если код вызывает его?

У меня есть следующий юнит-тест:

[TestClass]
public class DirectoryWatcherTests
{
    private AutoMoqer _mocker;
    private DirectoryWatcher _instance;

    [TestInitialize]
    public void Setup()
    {
        _mocker = new AutoMoqer();
        _instance = _mocker.Create<DirectoryWatcher>();
    }

    [TestMethod]
    public void Watcher_Gets_Path_Set_Same_As_Begin_Path_Parameter()
    {
        const string path = @"C:\test";
        _instance.Begin(path);

        _mocker.GetMock<FileSystemWatcherBase>()
               .VerifySet(x => x.Path = path);
    }
}

Код, который я написал, чтобы это передать:

public class DirectoryWatcher
{
    private readonly FileSystemWatcherBase _fileSystemWatcher;

    public DirectoryWatcher(FileSystemWatcherBase fileSystemWatcher)
    {
        _fileSystemWatcher = fileSystemWatcher;
    }

    public void Begin(string path)
    {
        if (string.IsNullOrWhiteSpace(path))
            throw new ArgumentException("FileSystemWatcher passed in without a valid path already set");

        _fileSystemWatcher.Path = path;
    }
}

Тем не менее VerifySet не удается с:

Ожидаемый вызов на макет хотя бы один раз, но так и не был выполнен: x => x.Path = "C:\test"

Почему он утверждает, что сеттер никогда не вызывается? Если это поможет вообще FileSystemWatcherBase это абстрактный класс.

1 ответ

Благодаря Евгению я понял, что это проблема с Automoq и его совместимостью с последней версией Unity. Я создал следующие тесты, чтобы доказать, что это проблема Automoq, а не проблема Moq:

    [TestMethod]
    public void Test()
    {
        const string path = @"C:\test";
        var watcherMock = new Mock<FileSystemWatcherBase>();
        watcherMock.Object.Path = path;
        watcherMock.VerifySet(x => x.Path = path);
    }

    [TestMethod]
    public void Test2()
    {
        const string path = @"C:\test";
        var mocker = new AutoMoqer();
        var instance = mocker.Create<Tester>();
        var watcherMock = mocker.GetMock<AbstractTest>();
        watcherMock.Object.Path = path;
        watcherMock.VerifySet(x => x.Path = path);
    }

    [TestMethod]
    public void Test3()
    {
        const string path = @"C:\test";
        var mocker = new AutoMoqer();
        var instance = mocker.Create<Tester>();
        var watcherMock = mocker.GetMock<AbstractTest>();
        instance.Run(path);
        watcherMock.VerifySet(x => x.Path = path);
    }

    [TestMethod]
    public void Test4()
    {
        const string path = @"C:\test";
        var testMock = _mocker.GetMock<AbstractTest>();
        var tester = new Tester(testMock.Object);
        tester.Run(path);

        testMock.VerifySet(x => x.Path = path);
    }

    public abstract class AbstractTest
    {
        public abstract string Path { get; set; }
    }

    public class Tester
    {
        private readonly AbstractTest _test;

        public Tester(AbstractTest test)
        {
            _test = test;
        }

        public void Run(string path)
        {
            _test.Path = path;
        }
    }

Тесты 1, 2 и 4 проходят, а 3 - не пройдены. Мне удалось найти решение этой проблемы с помощью следующего теста:

    [TestMethod]
    public void Test5()
    {
        const string path = @"C:\test";
        var mocker = new AutoMoqer();
        var watcherMock = mocker.GetMock<AbstractTest>();
        var instance = mocker.Create<Tester>();

        instance.Run(path);
        watcherMock.VerifySet(x => x.Path = path);
    }

По сути, наличие Automoq поможет мне до создания класса, который я пытаюсь протестировать, позволяет проверке работать. Это наводит меня на мысль, что Automoq не понимает, что moq уже был создан для тестируемого класса, и, следовательно, вызов GetMock<T> создает новый.

Другие вопросы по тегам