那今天的内容是延续昨天的商业逻辑所撰写的测试码,那接下来要探讨的议题是当 Load 方法要注入 Exception 的情境时,针对非同步处理要如何撰写,那在 NUnit3 的套件中有提供一个方法叫 Assert.ThrowsAsync,那其方法是类似於 Assert.Throws,应用於非同步的情境,测试码如下:
[Test]
public void FailedGet_Ver1()
{
// Arrange
var storage = Substitute.For<IStorage>();
storage.Load("key").Throws<TimeoutException>();
var cache = new DemoCache(storage);
// Act + Assert
Assert.ThrowsAsync<TimeoutException>(async () => await cache.Get("key"));
}
从这边我们可以看到,若使用 Assert.ThrowsAsync 的语法,在 Lambda 结构里就会去执行非同步处理;因此,从 Lambda 中就会取得相对应的值(范例为 string),所以在宣告的时候并不是用 async Task<string>,而是 void 方法。但倘若我们还要验证共执行几次,如下:
[Test]
public async Task FailedGet_Ver2()
{
// Arrange
var storage = Substitute.For<IStorage>();
storage.Load("key").Throws<TimeoutException>();
var cache = new DemoCache(storage);
// Act + Assert
Assert.ThrowsAsync<TimeoutException>(async () => await cache.Get("key"));
await storage.Received(1).Load("key");
}
因 Received() 需要等 cache.Get 执行完,因此就需要使用非同步语法。
接下来要探讨当 Returns 含有 Multiple Values 的时候,在搭配 Reload 的概念,把 Cache 里面的东西从 Storage 取出,每当执行 Load 的概念时,则会往後取一个数值,若已到最後一个时,则会固定在该数值,测试马如下:
[Test]
public async Task SingleGet_WithReload()
{
// Round 1
// Arrange
var storage = Substitute.For<IStorage>();
storage.Load("key").Returns("value1", "value2", "value3");
var cache = new DemoCache(storage);
// Act
var result1 = await cache.Get("key");
var result2 = await cache.Get("key");
// Assert
Assert.AreEqual(result1, "value1");
Assert.AreEqual(result2, "value1");
// Round 2
// Act
var result3 = await cache.Get("key");
// Assert
Assert.AreEqual(result3, "value2");
// Round 3
// Act
var result4 = await cache.Get("key");
var result5 = await cache.Get("key");
// Assert
Assert.AreEqual(result4, "value3");
Assert.AreEqual(result5, "value3");
// Round 4
// Act
var result6 = await cache.Get("key");
var result7 = await cache.Get("key");
// Assert
Assert.AreEqual(result6, "value3");
Assert.AreEqual(result7, "value3");
}
原参考来源是只测试两次,那为了示意每 Reload 会往後延一个以及固定在最後一个数值;因此,这边测试码写了 Reload 4 Round,并且在 Round 3 就已到第三个数值,Round 4 依旧在第三个数值。而最後的测试码是测试当有多个非同步执行的时候,两边执行的次数是否符合预期,测试码如下:
[Test]
public async Task MultipleGets_WithReload()
{
// Arrange
var storage = Substitute.For<IStorage>();
var cache = new DemoCache(storage);
// Act
await cache.Get("key1");
await cache.Get("key1");
await cache.Get("key2");
await cache.Get("key1");
await cache.Get("key2");
await cache.Get("key2");
await cache.Get("key2");
await cache.Get("key2");
// Assert
await storage.Received(2).Load("key1");
await storage.Received(3).Load("key2");
}
从这两天的范例可以看出测试码验证非同步处理与商业逻辑一样,都是要采用 Task、async 与 await 语法;但如果把 Act 的方法直接写在 Assert 的 Lambda 方法中,则宣告的时候则直接采用 void 即可(如 Exception 篇章),以及探讨 Returns 的用码。
>>: 【後转前要多久】# Day11 CSS - 区块元素、行内元素
前言 Hi, 我是鱼板伯爵今天要教大家 Row 这个容器,教学内容只会撷取片段程序码,建议大家搭配完...
在开始使用 React 之前,先来回想一下刚学习原生 JS 的时候,我们是怎麽在页面产生 DOM N...
Day29- 新手的Web系列JSON Injection 0x2 正文 web2.0导入了很多Aj...
在上一篇文章中提到,我们可以将不同类别当中的共同属性或方法,提取出来放在 parent 类别当中,然...
分享一些多年来专案管理及工作的心得: 专案是实现使命、愿景,及战略的具体努力。使命感、远见与作梦的能...