单元测试Mocks

一、简介

单元测试覆盖率越高,就能越早阶段发现错误,减少因设计、人员、变更带来的质量风险,这对于一个产品而言尤为重要。特别是对网络和环境的各种模拟,可以解决很多我们很多哪怕用人工测试手段都很难发现的问题。而Mock技术就是用来创建一个模拟的世界,这极大的简化接口本身对各种依赖所带来的测试难度。

二、检查用户名和密码

我们假定有个方法需要根据用户名和密码来检索用户信息,这可能会有以下规则:

  • 用户名不存在。
  • 密码不正确。
  • 用户被锁定。
  • 正确用户名和密码。

1、实现代码

public class UserRepository : IUserRepository
{
  private readonly IDataStore _store;

  public UserRepository(IDataStore store)
  {
    _store = store;
  }

  public User FindByCredentials(string username, string password)
  {
    var user = _store.FindOneByNamedQuery("FindUserByUserName", username);
    if (user == null) { return null; }
    return user.Password == password ? user : null;
  }
}

每一种规则可能返回的结果都不相同,但我们可以肯定的是想要做到这个测试,必须先保证 IDataStore 正确的加载,而正常他是访问数据库。

2、测试代码

[TestMethod]
public void ReturnsNullIfTheUserNameDontMatch()
{
    // 1、构建数据接口
    var store = new SqlDataStore();
    // 2、创建仓储实例
    IUserRepository userRep = new UserRepository(store);
    // 3、调用接口
    var res = userRep.FindByCredentials("asdf", "1");

    Assert.IsNull(res);
}

以上是针对当密码无法匹配时,其他情况的写法差不多;我简化很多代码,但是一个完整的单元示例就需要这么多。那么问题来了,数据库当中必须要先保证有一条 asdf 数据,而且为了保证测试通过还需要保证往后不能修改这条信息,否则这个测试将不再是有效的。

很自然看出这样的单元测试代码必须是依赖于数据库,我们示例给出的过于简单,现实需要的依赖的更多,比较我们不可能用明文保存密码,可能我们还需要依赖加密处理类。

3、使用Mock

Mock框架有很多,这里我采用 Moq。改写后的代码为:

[TestMethod]
public void ReturnsNullIfTheUserNameDontMatchByMock()
{
    // 通过Mock构建一个UserRepository实例,
    var userRep = new Mock<IUserRepository>();
    // 模拟用户名asdf 密码1 的结果
    userRep.Setup<User>(x => x.FindByCredentials("asdf", "1"))
           .Returns(new User()
           {
               IsNormal = true,
               Password = "1",
               UserName = "asdf"
           });

    // 当密码为1时应该返回一个User对象
    Assert.IsNotNull(userRep.Object.FindByCredentials("asdf", "1"));
    // 当密码为2时应该返回一个Null
    Assert.IsNull(userRep.Object.FindByCredentials("asdf", "2"));
}

相比较使用常规的写法,不再依赖于具体UserRepository,由接口模拟一条数据。

[SignalR2] WebSocket部署问题和优化若干问题

虽然关于部署会非常简单,也没有太多细节可以说。而了解一些相关性资料,这对于优化非常有帮助。

支持问题

我不知道算不算在澄清一个事实,那便是按微软给出的文档中必须是IIS8+才支持WebSocket协议,但好多资料文章都写着可以运用第三方扩展,我找过,但连接扩展文件的连接都失效。

WebSocket协议安装

默认情况下IIS是不会自动安装WebSocket协议的,介绍WIN8和WIN12的安装办法

web.config的 <webSocket> 节点

当IIS支持WebSocket协议后,我们就可以在web.config里面的 system.webServer/webSocket 下配置:

  • enabled:启用是否支持WebSocket。

  • pingInterval:WebSocket有支持ping/pong,用于持续连接(keep-alive)、心跳、网络状态检测、延迟测量等。但目前好像很多浏览器没有支持这一特性。

  • receiveBufferLimit:接收数据的缓存区大小。默认:4194304B。

SignalR 配置

Startup.cs 中,我们可以调用 GlobalHost.Configuration 来配置一些参数,以便于更高效的使用SignalR。

DefaultMessageBufferSize

用于缓冲消息数量,默认值:每个连接的每个Hub缓冲1000条。言下之意就是,当我们大量群发消息时,假如我们同一时刻向2000个用户发送消息,这可能会由于客户端接收响应比较慢,可能会倒置只有1500个用户会收到消息。

所以我们可以调整这个数字更大。方法也很简单:

GlobalHost.Configuration.DefaultMessageBufferSize = 2000;

对于大数据量的发送这种办法不非是完美的解决办法,最好是通过发送Ack包来检查是否发送成功,然后有节制性的逐批发送。

MaxIncomingWebSocketMessageSize

允许最大接收消息大小,默认是64KB。

IIS配置

WebSocket本身是一个协议,所以长连接或短连接这取决于IIS的配置。正因为如此,还得了解一下IIS上几个重要指标的配置。比如:每个应用程序的并发请求量、应用池请求队列大小等等。

参考资料

查看 SignalR系列文章

EPPLUS的一些应用

把今天做的一个EXCEL生成页面,也算是继.net操作Excel后,对EPPLUS在实际案例中分享一些做法。

首先EPPLUS的行与列都是从1开始算去,哪怕是合并单元格,也是如此。当然也支持地址格式选取方式,例如:A1、A1:A5。

1、创建新工作溥

var ws= pck.Workbook.Worksheets.Add(“汇总表”);

2、单元格赋值

ws.Cells[1, 1].Value = “”; 或 ws.Cells[“A1”].Value = “”;

3、行高、列宽

ws.Column(1).Width = 30f; // 第1列宽

ws.DefaultColWidth = 30f; // 默认所有列宽

ws.Row(1).Height = 20f; // 第1行高

ws.DefaultRowHeight = 20f; // 默认所有行高

4、自动调整列

ws.Cells.AutoFitColumns();

5、所有单元格自动换行

ws.Cells.Style.WrapText = true;

6、合并单元格

ws.Cells[1, 1, 1, 3].Merge = true; // 将A1:A3合并单元格

7、单元格样式

ws.Cells[1, 1].Style,在Style属性下,你可以设置:字体、边框、填充色、对齐方式。我重点讲一点不常用到的:

Indent:边框与文本之间的空白。

Locked:锁定单元格式(注:必须设置保护工作溥才有效)

Numberformat:数字型格式化,比如保留2位小数点“0.00”。另外一点需要注意的是,像日期格式化需要确保存储的值为DateTime,才会有效。例如:

ws.Cells[1, 1].Value = DateTime.Parse(oInfo[“CreateTime”].ToString());

ws.Cells[1, 1].Style.Numberformat.Format = “yyyy年MM月dd日”;

ShrinkToFit:缩小字体填充。

TextRotation:文字方向。

TextRotation:文字方向。

VerticalAlignment:垂直对齐。

HorizontalAlignment:水平对齐。

WrapText:自动换行。

Hidden:单元格隐藏。

© 2017 卡片机色彩 沪ICP备13032872号-3

Theme by cipchk

to top