c # Moq объект void метод, который изменяет значение параметра объектов - PullRequest
0 голосов
/ 16 сентября 2018

Я пытаюсь использовать Mocks в своем модульном тестировании, но я борюсь с приведенным ниже кодом. Я хочу правильно вызвать метод Callback из метода AppendName, чтобы этот метод был правильно протестирован и имя измененного объекта действительно изменилось.

public class GenericTests
{
   [TestMethod]
   public void TestMethod1()
   {
       IFile newFile = GetNewFile("Document").Object;
       newFile.AppendName();
       Assert.AreEqual("AppendedDocument", newFile.Name);
   }

   public Mock<IFile> GetNewFile(string name)
   {
       Mock<IFile> file = new Mock<IFile>();
       file.Setup(f => f.Name).Returns(name);
       file.Setup(f => f.Path).Returns(@"C:\Folder\" + name);
       file.Setup(f => f.AppendName()).Callback.....problem is here.....

        return file;
   }
}
public interface IFile
{
    string Name { get; set; }
    string Path { get; set; }
    void AppendName();
}
public class LocalFile : IFile
{
    public string Name { get; set; }
    public string Path { get; set; }
    public void AppendName()
    {
        this.Name = "AppendedDocument";
    }
} 

Может кто-нибудь подсказать, пожалуйста, как завершить обратный вызов для AppendName () ??? пожалуйста * * 1004

1 Ответ

0 голосов
/ 16 сентября 2018

Видите ли, интерфейс IFile и класс LocalFile - это разные типы. Поэтому мы не можем заставить Mock<IFile> воспроизводить реализацию из LocalFile по умолчанию. Чтобы ваш тест работал, вы можете добавить следующий Callback звонок:

public Mock<IFile> GetNewFile(string name)
{                
    Mock<IFile> file = new Mock<IFile>();
    file.CallBase = true;
    file.Setup(f => f.Name).Returns(name);
    file.Setup(f => f.Path).Returns(@"C:\Folder\" + name);
    file.Setup(f => f.AppendName()).Callback(() => file.Setup(f => f.Name).Returns(() => 
    {
        var localFile = new LocalFile();
        localFile.AppendName();
        return localFile.Name;
        // or just return "AppendedDocument"
    }));   

    return file;
} 

Пример работает, однако, это не то, что вам нужно, я полагаю. Даже для Mock<LocalFile> с CallBase = true и public virtual public string Name { get; set; } вам нужно как-то очистить настройку свойства. Насколько я знаю, Moq не позволяет этого. Я могу ошибаться. Вы можете попробовать следующий обходной путь, основанный на той же идее:

public class GenericTests
{
    [Test]
    public void TestMethod1()
    {
        IFile newFile = GetNewFile("Document");
        newFile.AppendName();
        Assert.AreEqual("AppendedDocument", newFile.Name);
    }

    public IFile GetNewFile(string name)
    {
        Mock<LocalFile> file = new Mock<LocalFile>();
        file.CallBase = true;
        file.Object.AppendName();
        // remember expected result before setting up the mock
        var appendDoc = file.Object.Name;
        file.Setup(f => f.Name).Returns(name);
        file.Setup(f => f.Path).Returns(@"C:\Folder\" + name);
        file.Setup(f => f.AppendName())
            // change property behavior after call of AppendName 
            .Callback(() => file.Setup(f => f.Name).Returns(appendDoc));
        return file.Object;
    }
}

public interface IFile
{
    string Name { get; set; }
    string Path { get; set; }
    void AppendName();
}

public class LocalFile : IFile
{
    public virtual string Name { get; set; }
    public virtual string Path { get; set; }
    public virtual void AppendName()
    {
        this.Name = "AppendedDocument";
    }
}

Я немного изменил ваш пример. GetNewFile теперь возвращает IFile экземпляр, и члены LocalFile стали виртуальными. Надеюсь, это поможет.

...