首页 > 解决方案 > c# Moq objects void方法,改变objects参数值

问题描述

我正在尝试在我的单元测试中使用 Mocks,但我在下面的代码中遇到了困难。我想以正确的方式从 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() 的回调吗?请

标签: c#mockingmoq

解决方案


你看,接口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>with CallBase = truepublic virtual public string Name { get; set; }您也需要以某种方式清除属性设置。据我所知,起订量不允许这样做。我可能是错的。您可以基于相同的想法尝试下一个解决方法:

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成为虚拟的成员。希望能帮助到你。


推荐阅读