一个方便IO单元测试的C#扩展库
对于我们.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#扩展库的更多相关文章
- Z.ExtensionMethods 一个强大的开源扩展库
今天有意的在博客园里面搜索了一下 Z.ExtensionMethods 这个扩展类库,确发现只搜到跟这个真正相关的才两篇博文而已,我都点进去看了一下,也都只是提到而已,没有专门介绍,才引起我写这篇文档 ...
- Python环境——安装扩展库
一.修改easy_install源 在操作用户家目录添加一个文件 cat >> ~/.pydistutils.cfg <<EOF [easy_install] index-ur ...
- ASP.NET MVC扩展库
很多同学都读过这篇文章吧 ASP.NET MVC中你必须知道的13个扩展点,今天给大家介绍一个ASP.NET MVC的扩展库,主要就是针对这些扩展点进行.这个项目的核心是IOC容器,包括Ninject ...
- ASP.NET Core扩展库之Http请求模拟
如今,完全独立的业务应用几乎不存在,不管是在企业内部微服务之间的调用,还是与外部第三方服务的调用,Http的API交互是常见的场景,这些实际情况给我们的开发带来了比较大的挑战,一是第三方服务可能会牵制 ...
- PHP使用mysqli扩展库实现增删改查(面向对象版)
mysqli扩展库是mysql扩展库的改进版本,在mysql扩展库的基础上提高了稳定性和效率,mysqli扩展库有两套东西,一套就是面向过程的mysqli另一套是面向对象的mysqli.操作方式大体和 ...
- PHP mysqli 扩展库(面向对象/数据库操作封装/事务控制/预编译)
1.和mysql扩展库的区别: (1 安全性.稳定性更高 (2 提供了面向对象和面向过程两种风格 2.php.ini 中的 extension=php_mysqli.dll 解除封印 3.面 ...
- PHP基础Mysql扩展库
mysql扩展库操作步骤如下: 1.连接数据库 2.选择数据库 3.设置操作编码 4.发送指令sql,并返回结果集 ddl:数据定义语句 dml:数据操作语句 dql:数据查询 ...
- mysql扩展库-1
启用mysql扩展库 在php.ini文件中去配置mysql扩展库 extension=php_mysql.dll 可以通过 phpinfo() 查看当前php支持什么扩展库. 在sql扩展库中创建一 ...
- 安装php扩展库
无法加载'pdo_mysql' ,因为需要pdo这个module.PHP Warning: Cannot load module 'pdo_mysql' because required module ...
- EF扩展库(批量操作)
EF删除和修改数据只能先从数据库取出,然后再进行删除 delete from Table1 where Id>5; update Table1 set Age=10; 我们需要这样操作 //删除 ...
随机推荐
- 【深入浅出Spring原理及实战】「源码原理实战」从底层角度去分析研究PropertySourcesPlaceholderConfigurer的原理及实战注入机制
Spring提供配置解析功能 主要有一下xml文件占位符解析和Java的属性@Value的占位符解析配置这两种场景进行分析和实现解析,如下面两种案例. xml文件的占位符解析配置 <bean i ...
- [编程基础] Python数据生成库Faker总结
Python Faker教程展示了如何使用Faker软件包在Python中生成伪数据.我们使用joke2k/faker包. 1 介绍 Faker是一个生成假数据的Python库.伪数据通常用于测试或用 ...
- Hive详解(06) - Hive调优实战
Hive详解(06) - Hive调优实战 执行计划(Explain) 基本语法 EXPLAIN [EXTENDED | DEPENDENCY | AUTHORIZATION] query 案例实操 ...
- 基于docker容器的MySQL主从设置及efcore读写分离
1.基于docker部署MySQL,设置主从 本操作基于已经拉取的镜像(docker pull mysql) 创建一主一从两个数据库容器 docker run -d -p 3307:3306 -e M ...
- 2022CSP-J线上游记
写在前面 安徽CSP取消了-- 去年CSP考炸的我本来想今年一雪前耻(bushi),结果-- T1 第一题大毒瘤! 首先观察数据可以分类如下两种情况: \(a = 1\) 直接输出\(1\),retu ...
- Redis缓存何以一枝独秀?——从百变应用场景与热门面试题中感受下Redis的核心特性与使用注意点
大家好,又见面了. 本文是笔者作为掘金技术社区签约作者的身份输出的缓存专栏系列内容,将会通过系列专题,讲清楚缓存的方方面面.如果感兴趣,欢迎关注以获取后续更新. 作为<深入理解缓存原理与实战设计 ...
- 03-逻辑综合工具 - Design Compiler
逻辑综合工具DC IC设计流程,市场-->制定spec-->RTL(同时进行sim,通过alint检查RTL有没有错误)-->systhesis(逻辑综合)-->PR(STA) ...
- 蓝桥真题——最短路 & 门牌制作
题目1 最短路 标签:填空题 2019 省赛 如下图所示,G 是一个无向图,其中蓝色边的长度是 1.橘色边的长度是 2.绿色边的长度是 3. 则从 A 到 S 的最短距离是多少? 答案 由图可得,最短 ...
- Nodejs后端自动化测试
偶然看到收藏一下 const puppeteer = require('puppeteer'); const fs = require('fs'); (async () => { const b ...
- angular 父组件调用子组件方法---以及组件跨模块使用方法
如果要在父组件调用子组件 可以这样子 @ViewChild('mySun', { static: false }) mySun: MySunComponent; 使用方法: let res=this. ...