3

次の単体テストがあります。

[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エラーで失敗します。

少なくとも 1 回はモックでの呼び出しが期待されていましたが、実行されませんでした: x => x.Path = "C:\test"

セッターが呼び出されないと主張しているのはなぜですか? それがまったく役立つ場合FileSystemWatcherBaseは、抽象クラスです。

4

1 に答える 1

3

Eugene のおかげで、これは Automoq と最新バージョンの Unity との互換性の問題であると思われることがわかりました。Moq の問題ではなく Automoq の問題であることを証明するために、次のテストを作成しました。

    [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>によって新しい moq が作成されると考えられます。

于 2014-02-23T16:25:06.373 に答える