我有以下代码用于从Zip添加/解压缩。我正在尝试重构这个以使其准备好测试。有人可以提供我如何实现这一目标的指示吗? 旁白:我使用Moq作为我的模拟框架,使用MSTest作为我的单元测试工具
private const long BufferSize = 4096;
public static void ExtractZip(string zipFilename, string folder) {
using (var zip = System.IO.Packaging.Package.Open(zipFilename, FileMode.OpenOrCreate)) {
foreach (var part in zip.GetParts()) {
using (var reader = new StreamReader(part.GetStream(FileMode.Open, FileAccess.Read))) {
using (var writer = new FileStream(folder + "\\" + Path.GetFileName(part.Uri.OriginalString),
FileMode.Create, FileAccess.Write)) {
var buffer = System.Text.Encoding.UTF8.GetBytes(reader.ReadToEnd());
writer.Write(buffer, 0, buffer.Length);
}
}
}
}
}
public static void AddFileToZip(string zipFilename, string fileToAdd) {
using (var zip = System.IO.Packaging.Package.Open(zipFilename, FileMode.OpenOrCreate)) {
var destFilename = ".\\" + Path.GetFileName(fileToAdd);
var uri = PackUriHelper.CreatePartUri(new Uri(destFilename, UriKind.Relative));
if (zip.PartExists(uri)) {
zip.DeletePart(uri);
}
var part = zip.CreatePart(uri, "", CompressionOption.Normal);
using (var fileStream = new FileStream(fileToAdd, FileMode.Open, FileAccess.Read)) {
using (var dest = part.GetStream()) {
CopyStream(fileStream, dest);
}
}
}
}
提前致谢。
答案 0 :(得分:2)
我会制作这两个静态方法(ExtractZip和AddFileToZip)实例方法,并将其放入一个接口:
public interface IZipper
{
void ExtractZip(string zipFilename, string folder);
void AddFileToZip(string zipFilename, string fileToAdd);
}
public class Zipper : IZipper
{
public void ExtractZip(string zipFilename, string folder)
{
//...
}
void AddFileToZip(string zipFilename, string fileToAdd)
{
//...
}
}
// client code
class Foo
{
private IZipper myZipper;
// gets an instance of the zipper (injection), but implements only
// against the interface. Allows mocks on the IZipper interface.
public Foo(IZipper zipper)
{
myZipper = zipper;
}
}
客户端代码现在很容易测试。
拉链类怎么样?
答案 1 :(得分:0)
摘要FileStream
在IStreamProvider
后面的创建,并将其传递给AddFileToZip
和ExtractZip
。除非您愿意在进行单元测试时执行磁盘IO,否则您将不得不抽象文件系统操作。
答案 2 :(得分:0)
我在这里粘贴最终代码,因为它可能对某人有所帮助,也让我得到反馈。 感谢Stefan指出我正确的方向。
/// <summary>
/// The commented methods are marked for future
/// </summary>
public interface IZipper
{
//void Create();
void ExtractAll();
void ExtractAll(string folder);
//void Extract(string fileName);
void AddFile(string fileName);
//void DeleteFile(string fileName);
}
public interface IZipStreamProvider
{
Stream GetStream(string fileName);
}
public class ZipStreamProvider : IZipStreamProvider
{
public Stream GetStream(string fileName)
{
//Create a read/writable file
return new FileStream(fileName, FileMode.Create);
}
}
public class Zipper : IZipper
{
private const long BufferSize = 4096;
public string ZipFileName { get; set;}
//seam.. to use property injection
private IZipStreamProvider ZipStreamProvider { get; set;}
public Zipper(string zipFilename)
{
ZipFileName = zipFilename;
//By default, write to file
ZipStreamProvider = new ZipStreamProvider();
}
public void ExtractAll()
{
ExtractAll(Environment.CurrentDirectory);
}
public void ExtractAll(string folder)
{
using (var zip = System.IO.Packaging.Package.Open(ZipStreamProvider.GetStream(ZipFileName)))
{
foreach (var part in zip.GetParts())
{
using (var reader = new StreamReader(part.GetStream(FileMode.Open, FileAccess.Read)))
{
using (var writer = ZipStreamProvider.GetStream(folder + "\\" + Path.GetFileName(part.Uri.OriginalString)))
{
var buffer = System.Text.Encoding.UTF8.GetBytes(reader.ReadToEnd());
writer.Write(buffer, 0, buffer.Length);
}
}
}
}
}
public void AddFile(string fileToAdd)
{
using (var zip = System.IO.Packaging.Package.Open(ZipFileName, FileMode.OpenOrCreate))
{
var destFilename = ".\\" + Path.GetFileName(fileToAdd);
var uri = PackUriHelper.CreatePartUri(new Uri(destFilename, UriKind.Relative));
if (zip.PartExists(uri))
{
zip.DeletePart(uri);
}
var part = zip.CreatePart(uri, "", CompressionOption.Normal);
using (var fileStream = ZipStreamProvider.GetStream(fileToAdd))
{
using (var dest = part.GetStream())
{
CopyStream(fileStream, dest);
}
}
}
}
private long CopyStream(Stream inputStream, Stream outputStream)
{
var bufferSize = inputStream.Length < BufferSize ? inputStream.Length : BufferSize;
var buffer = new byte[bufferSize];
int bytesRead;
var bytesWritten = 0L;
while ((bytesRead = inputStream.Read(buffer, 0, buffer.Length)) != 0)
{
outputStream.Write(buffer, 0, bytesRead);
bytesWritten += bufferSize;
}
return bytesWritten;
}
}
/// <summary>
/// The commented methods are marked for future
/// </summary>
public interface IZipper
{
//void Create();
void ExtractAll();
void ExtractAll(string folder);
//void Extract(string fileName);
void AddFile(string fileName);
//void DeleteFile(string fileName);
}
public interface IZipStreamProvider
{
Stream GetStream(string fileName);
}
public class ZipStreamProvider : IZipStreamProvider
{
public Stream GetStream(string fileName)
{
//Create a read/writable file
return new FileStream(fileName, FileMode.Create);
}
}
public class Zipper : IZipper
{
private const long BufferSize = 4096;
public string ZipFileName { get; set;}
//seam.. to use property injection
private IZipStreamProvider ZipStreamProvider { get; set;}
public Zipper(string zipFilename)
{
ZipFileName = zipFilename;
//By default, write to file
ZipStreamProvider = new ZipStreamProvider();
}
public void ExtractAll()
{
ExtractAll(Environment.CurrentDirectory);
}
public void ExtractAll(string folder)
{
using (var zip = System.IO.Packaging.Package.Open(ZipStreamProvider.GetStream(ZipFileName)))
{
foreach (var part in zip.GetParts())
{
using (var reader = new StreamReader(part.GetStream(FileMode.Open, FileAccess.Read)))
{
using (var writer = ZipStreamProvider.GetStream(folder + "\\" + Path.GetFileName(part.Uri.OriginalString)))
{
var buffer = System.Text.Encoding.UTF8.GetBytes(reader.ReadToEnd());
writer.Write(buffer, 0, buffer.Length);
}
}
}
}
}
public void AddFile(string fileToAdd)
{
using (var zip = System.IO.Packaging.Package.Open(ZipFileName, FileMode.OpenOrCreate))
{
var destFilename = ".\\" + Path.GetFileName(fileToAdd);
var uri = PackUriHelper.CreatePartUri(new Uri(destFilename, UriKind.Relative));
if (zip.PartExists(uri))
{
zip.DeletePart(uri);
}
var part = zip.CreatePart(uri, "", CompressionOption.Normal);
using (var fileStream = ZipStreamProvider.GetStream(fileToAdd))
{
using (var dest = part.GetStream())
{
CopyStream(fileStream, dest);
}
}
}
}
private long CopyStream(Stream inputStream, Stream outputStream)
{
var bufferSize = inputStream.Length < BufferSize ? inputStream.Length : BufferSize;
var buffer = new byte[bufferSize];
int bytesRead;
var bytesWritten = 0L;
while ((bytesRead = inputStream.Read(buffer, 0, buffer.Length)) != 0)
{
outputStream.Write(buffer, 0, bytesRead);
bytesWritten += bufferSize;
}
return bytesWritten;
}
}