使用Shims for ZipFile进行单元测试

时间:2015-12-09 10:24:53

标签: c# unit-testing zip moq shim

我试图对使用ZipFile.OpenRead的一些代码进行单元测试,从ZIP中提取一些XML文件(用moq编写单元测试)

有没有办法用我自己的结果替换对ZipFile.OpenRead的调用?我已经在类似的情况下使用垫片,但是我无法弄清楚在这种情况下该做什么,并且有关垫片的文档非常稀疏。

以下是需要进行单元测试的方法(部分):

    public IEnumerable<ConfigurationViewModel> ExtractXmlFromZip(string fileName)
    {
        var configs = new List<ConfigurationViewModel>();
        using (var archive = ZipFile.OpenRead(fileName))
        {
            foreach (ZipArchiveEntry entry in archive.Entries)
            {
                if (entry.FullName.EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
                {
                    LoadConfigfromZipArchiveEntry(entry, configs)
                }
            }
        }
        return configs;
   }

2 个答案:

答案 0 :(得分:2)

没有办法使用mock模拟像ZipFile这样的静态类,你可以使用IZipFileWrapper(比如说)来包装它

public IZipFileWrapper
{
     ZipArchive OpenRead(string fileName)
}

public ZipFileWrapper : IZipFileWrapper
{
   public ZipArchive OpenRead(string fileName)
   {
     return ZipFile.OpenRead(fileName)
   }
}

然后代码变为:

public MyObj
{
   private IZipFileWrapper zipFileWrapper;

   public MyObj(IZipFileWrapper zipFileWrapper)
   {
      this.zipFileWrapper = zipFileWrapper;
   }

   public IEnumerable<ConfigurationViewModel> ExtractXmlFromZip(string fileName)
   {
       var configs = new List<ConfigurationViewModel>();
       // Call the wrapper
       using (var archive = this.zipFileWrapper.OpenRead(fileName))
       {
           foreach (ZipArchiveEntry entry in archive.Entries)
           {
              if (entry.FullName.EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
              {
                  LoadConfigfromZipArchiveEntry(entry, configs)
              }
           }
       }
       return configs;
    }
}

的测试
[TestMethod]
public void ExtractXmlFromZip_Test()
{
    var myThing = new MyObj();
    var fileName = "my.zip";
    ZipArchive myZipArchive = CreateTestZipFile(); // Set up your return

    var mockWrapper = new Mock<IZipFileWrapper>();    
    mockWrapper.Setup(m => m.OpenRead(fileName)).Returns(myZipArchive);

        var configs = myThing.ExtractXmlFromZip(fileName);
        // Assert
    }
}

你可能需要包装更多以获得该传递,但希望这显示了这个概念。

<小时/> (在我意识到这是你要求的moq并且不是来自Microsoft Fakes的垫片之前写过这个)
有一种更简单的方法可以使用可以获得此代码的Shims - 来自Microsoft Fakes。 https://developers.facebook.com/docs/graph-api/reference/v2.5/user/friends类是System.IO.Compression.FileSystem的一部分,它位于同名的dll中。

要让我们使用ShimZipFile,我们需要添加一个Fakes Assembly:

注意:我们需要伪造System.IO.Compression.FileSystem(即dll) System.IO.Compression dlll(ZipFile的名称空间)。

ZipFile

应该对项目进行以下更改:

enter image description here

enter image description here

然后我们可以在以下测试中使用它:

[TestMethod]
public void ExtractXmlFromZip_Test()
{
    var myThing = new MyObj();
    var fileName = "my.zip";
    ZipArchive myZipArchive = CreateTestZipFile(); // Set up your return
    using (ShimsContext.Create())
    {
        System.IO.Compression.Fakes.ShimZipFile.OpenReadString = (filename) => myZipArchive;
        var configs = myThing.ExtractXmlFromZip(fileName);
        // Assert
    }
}

MSDN上有关于假货产生的垫片enter image description here的信息。

答案 1 :(得分:0)

我最近采用的一种方法是在类上使用私有委托成员,其目的是包装具体实现。

幸运的是,对我来说,R#可以很容易地创建一个具有单个私有成员的具体代理类,在包装类型上公开公共成员(通过Delegate Members代码生成器),然后提取接口以解耦,并提供在测试过程中模拟和验证的方法。