对于我们.Net程序员,System.Web.Abstractions我们都非常熟悉,主要作用于Web可以实现单元测试,他是在.Net framework 3.5 sp1开始引入的,很好的解决项目表示层不好做单元测试的问题,这个库所有类都是Wrapper/Decorator模式的。今天给推荐一个IO的扩展库与System.Web.Abstractions一样的,用来支持IO实现单元测试功能。

项目简介

一个支持IO实现单元测试的扩展库,支持跨平台,与File所有API接口都一样,方便我们项目扩展、迁移。

项目结构

项目主要核心文件是IFileSystem和FileSystem。

 

技术架构

1、平台:基于Net4、Netstandard2.0开发

2、开发工具:Visual Studio 2017

使用方法

读取文本使用例子,使用方法与File类一样,都是使用相同API名ReadAllText,只是这个API支持可注入和可测试的。

public class MyComponent{readonly IFileSystem fileSystem;
// <summary>Create MyComponent with the given fileSystem implementation</summary>public MyComponent(IFileSystem fileSystem) {this.fileSystem = fileSystem; }/// <summary>Create MyComponent</summary>public MyComponent() : this( fileSystem: new FileSystem() //use default implementation which calls System.IO ) { }
public void Validate() {foreach (var textFile in fileSystem.Directory.GetFiles(@"c:\", "*.txt", SearchOption.TopDirectoryOnly)) {var text = fileSystem.File.ReadAllText(textFile);if (text != "Testing is awesome.")throw new NotSupportedException("We can't go on together. It's not me, it's you."); } }}

文件创建单元测试

[Test]public void Mockfile_Create_ShouldCreateNewStream() {string fullPath = XFS.Path(@"c:\something\demo.txt");var fileSystem = new MockFileSystem(); fileSystem.AddDirectory(XFS.Path(@"c:\something"));
var sut = new MockFile(fileSystem);
Assert.That(fileSystem.FileExists(fullPath), Is.False);
sut.Create(fullPath).Dispose();
Assert.That(fileSystem.FileExists(fullPath), Is.True); }

删除文件单元测试

[Test]public void MockFile_Delete_ShouldDeleteFile() {var fileSystem = new MockFileSystem();var path = XFS.Path("C:\\test");var directory = fileSystem.Path.GetDirectoryName(path); fileSystem.AddFile(path, new MockFileData("Bla"));
var fileCount1 = fileSystem.Directory.GetFiles(directory, "*").Length; fileSystem.File.Delete(path);var fileCount2 = fileSystem.Directory.GetFiles(directory, "*").Length;
Assert.AreEqual(1, fileCount1, "File should have existed"); Assert.AreEqual(0, fileCount2, "File should have been deleted"); }

文件复制单元测试

[Test]public void MockFile_Copy_ShouldOverwriteFileWhenOverwriteFlagIsTrue() {string sourceFileName = XFS.Path(@"c:\source\demo.txt");var sourceContents = new MockFileData("Source content");string destFileName = XFS.Path(@"c:\destination\demo.txt");var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData> { {sourceFileName, sourceContents}, {destFileName, new MockFileData("Destination content")} });
fileSystem.File.Copy(sourceFileName, destFileName, true);
var copyResult = fileSystem.GetFile(destFileName); Assert.AreEqual(copyResult.Contents, sourceContents.Contents); }

文件移动单元测试

[Test]public void MockFile_Move_ShouldMoveFileWithinMemoryFileSystem() {string sourceFilePath = XFS.Path(@"c:\something\demo.txt");string sourceFileContent = "this is some content";var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData> { {sourceFilePath, new MockFileData(sourceFileContent)}, {XFS.Path(@"c:\somethingelse\dummy.txt"), new MockFileData(new byte[] {0})} });
string destFilePath = XFS.Path(@"c:\somethingelse\demo1.txt");
fileSystem.File.Move(sourceFilePath, destFilePath);
Assert.That(fileSystem.FileExists(destFilePath), Is.True); Assert.That(fileSystem.GetFile(destFilePath).TextContents, Is.EqualTo(sourceFileContent)); Assert.That(fileSystem.FileExists(sourceFilePath), Is.False); }

支持 .NET Framework用法

FileInfo SomeBadApiMethodThatReturnsFileInfo(){return new FileInfo("a");}void MyFancyMethod(){var testableFileInfo = (FileInfoBase)SomeBadApiMethodThatReturnsFileInfo();    ...}

项目地址:https://github.com/Haydabase/System.IO.Abstractions

一个方便IO单元测试的C#扩展库的更多相关文章

  1. Z.ExtensionMethods 一个强大的开源扩展库

    今天有意的在博客园里面搜索了一下 Z.ExtensionMethods 这个扩展类库,确发现只搜到跟这个真正相关的才两篇博文而已,我都点进去看了一下,也都只是提到而已,没有专门介绍,才引起我写这篇文档 ...

  2. Python环境——安装扩展库

    一.修改easy_install源 在操作用户家目录添加一个文件 cat >> ~/.pydistutils.cfg <<EOF [easy_install] index-ur ...

  3. ASP.NET MVC扩展库

    很多同学都读过这篇文章吧 ASP.NET MVC中你必须知道的13个扩展点,今天给大家介绍一个ASP.NET MVC的扩展库,主要就是针对这些扩展点进行.这个项目的核心是IOC容器,包括Ninject ...

  4. ASP.NET Core扩展库之Http请求模拟

    如今,完全独立的业务应用几乎不存在,不管是在企业内部微服务之间的调用,还是与外部第三方服务的调用,Http的API交互是常见的场景,这些实际情况给我们的开发带来了比较大的挑战,一是第三方服务可能会牵制 ...

  5. PHP使用mysqli扩展库实现增删改查(面向对象版)

    mysqli扩展库是mysql扩展库的改进版本,在mysql扩展库的基础上提高了稳定性和效率,mysqli扩展库有两套东西,一套就是面向过程的mysqli另一套是面向对象的mysqli.操作方式大体和 ...

  6. PHP mysqli 扩展库(面向对象/数据库操作封装/事务控制/预编译)

    1.和mysql扩展库的区别: (1   安全性.稳定性更高 (2  提供了面向对象和面向过程两种风格 2.php.ini  中的  extension=php_mysqli.dll 解除封印 3.面 ...

  7. PHP基础Mysql扩展库

    mysql扩展库操作步骤如下: 1.连接数据库 2.选择数据库 3.设置操作编码 4.发送指令sql,并返回结果集     ddl:数据定义语句     dml:数据操作语句     dql:数据查询 ...

  8. mysql扩展库-1

    启用mysql扩展库 在php.ini文件中去配置mysql扩展库 extension=php_mysql.dll 可以通过 phpinfo() 查看当前php支持什么扩展库. 在sql扩展库中创建一 ...

  9. 安装php扩展库

    无法加载'pdo_mysql' ,因为需要pdo这个module.PHP Warning: Cannot load module 'pdo_mysql' because required module ...

  10. EF扩展库(批量操作)

    EF删除和修改数据只能先从数据库取出,然后再进行删除 delete from Table1 where Id>5; update Table1 set Age=10; 我们需要这样操作 //删除 ...

随机推荐

  1. Jenkins&&gitlab2

    Jenkins  slave 添加jenkins slave节点: jenkins slave节点创建工作目录与基本环境配置,如果jenkins slave节点需要clone代码和执行java 代码编 ...

  2. Vuex从入门到精通

    一.vuex介绍 目标 什么是Vuex 为什么学习Vuex 通信方案 组件关系 数据通信 父子关系 父传子:props : 子传父:$emit 非父子关系 vuex (一种组件通信方案) Vuex是什 ...

  3. go语言的切片特性

    概述: 在使用切片进行赋值的时候,产生新的数组的指针指向原来的数组,只要修改新数组中的元素时,原来数组的元素也会改变. 测试代码: func TestSliceShareMemory(t *testi ...

  4. 2022i春秋-冬季赛nan’s analysis

    下载附件,在tcp的0流可以看到一个keyisChunqiuGame00504 在3流处得到压缩包,密码不是上面那个,后面对附件找了几个小时都没发现压缩包密码,我是笨比.后面才看到有在线环境. 然后找 ...

  5. Python实验报告(第2章)

    实验2:Python语言基础 一.实验目的和要求 1.了解Python的编写规范要求: 2.了解Python的基本数据类型: 3.学会使用Python的五种运算符: 4.掌握Python的基本输入和输 ...

  6. [R语言] ggplot2入门笔记4—前50个ggplot2可视化效果

    文章目录 通用教程简介(Introduction To ggplot2) 4 ggplot2入门笔记4-前50个ggplot2可视化效果 1 相关性(Correlation) 1.1 散点图(Scat ...

  7. DVWA靶场实战(七)——SQL Injection

    DVWA靶场实战(七) 七.SQL Injection: 1.漏洞原理: SQL Inject中文叫做SQL注入,是发生在web端的安全漏洞,主要是实现非法操作,例如欺骗服务器执行非法查询,他的危害在 ...

  8. 一、tcp三次握手

    (1)首先客户端向服务器端发送一段tcp报文,其中标志位为SYN,表示"请求创建新连接"序列号为sqe=x,随后进入SYN_SEND状态 (2)服务器端接受到客户端发送的tcp报文 ...

  9. Codeforces Round #569 (Div. 2)

    题解 Codeforces Round #569 (Div. 2) rank:1306/11165 rate: +43 1424 → 1467 Codeforces Round #569 (Div. ...

  10. Python 内置界面开发框架 Tkinter入门篇

    本文大概 4158 个字,阅读需花 10 分钟 内容不多,但也花了一些精力 如要交流,欢迎关注我然后评论区留言 谢谢你的点赞收藏分享 首先,今天先给大家拜个好年!新年快乐,恭喜发财!为了感谢大家对我的 ...