NUnit
前情提要
以下範例是 .NET Core 6.0.0 的範例
需要額外下載套件
Moq (用來做 mockito 的相關行為)
FluentAssertions (用來提升可讀性)
單元測試
硬斷言
[Test]
public void Hard_Assertion()
{
// Arrange
string str = "123";
string expected = "2";
// Act
string actual = str.Substring(1, 1);
// Assert
// 原生寫法
Assert.AreEqual(actual, expected);
// 使用 FluentAssertions 提升可讀性
actual.Should().Be(expected);
}
軟斷言
[Test]
public void Soft_Assertion()
{
// Arrange
string str = "123";
// Act
string actual1 = str.Substring(1, 1);
string actual2 = str.Substring(1, 2);
// Assert
// 原生寫法
Assert.Multiple(() =>
{
Assert.AreEqual("2",actual1);
Assert.AreEqual("23",actual2);
});
// 使用 FluentAssertions 提升可讀性
using (new AssertionScope())
{
actual1.Should().Be("2");
actual2.Should().Be("23");
}
}
驗證 Exception
[Test]
public void Throwing_Exception()
{
// Arrange
// 原生寫法
// Act
var ex = Assert.Throws<Exception>(()=>throwException());
// Assert
Assert.That(ex.Message, Does.Contain("Magic"));
// 使用 FluentAssertions 提升可讀性
// Act
Action actual = () => throwException();
// Assert
actual.Should().Throw<Exception>().WithMessage("*Magic*");
}
private void throwException()
{
throw new Exception("Magic");
}
API 測試
參考資料:(https://www.ruyut.com/2023/04/nunit-aspnet-core6-api-integration-testing.html)
*還有重構空間,此處僅是API測試的範例,可讀性方面請參考單元測試部分
using System.Text;
using Microsoft.AspNetCore.Mvc.Testing;
using Newtonsoft.Json;
using JsonSerializer = System.Text.Json.JsonSerializer;
namespace {namespace};
public class {controllerName}Test
{
private WebApplicationFactory<Program> _factory = null!;
private HttpClient _client = null!;
[OneTimeSetUp]
public void Init()
{
_factory = new WebApplicationFactory<Program>();
_client = _factory.CreateClient();
// 這行會切正式環境,拿掉就是測試環境 Debugger
// Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT","Production"); //正式環境
Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development"); //測試環境
}
[OneTimeTearDown]
public void Cleanup()
{
_factory.Dispose();
}
[Test]
public async Task {MethodName}_{type}()
{
// Arrange
var type = "keyWord";
string id= "id";
var url = $"url{type}?id={id}";
// Act
var response = await WhenGet<JsonResultBase>(url);
// Assert
ShouldBeSuccessHasData(response);
{MethodName}ResponseShouldBe(response!.data);
}
[Test]
public async Task {MethodName}_{type}()
{
// Arrange
var type = "keyword2";
string id= "id";
string day = "1";
var url = $"url{type}?id={id}&day={day}";
// Act
var response = await WhenGet<JsonResultBase>(url);
// Assert
ShouldBeSuccessHasData(response);
{MethodName}ResponseShouldBe(response!.data);
}
[Test]
public async Task {MethodName}_{type}_shouldBeNull()
{
// Arrange
var type = "type";
string id= "id";
var url = $"url{type}?id={id}&day={day}";
// Act
var response = await WhenGet<JsonResultBase>(url);
// Assert
ShouldBeSuccessHasData(response);
{MethodName}ResponseShouldBeNull(response!.data);
}
private async Task<T?> WhenGet<T>(string url)
{
var response = await _client.GetAsync(url);
var content = await response.Content.ReadAsStringAsync();
//Console.Out.WriteLine(content);
T? responseBase = JsonConvert.DeserializeObject<T>(content);
return responseBase;
}
private static void ShouldBeSuccessHasData(JsonResultBase? responseBase)
{
Assert.IsTrue(responseBase.success);
Assert.IsNull(responseBase.message);
Assert.IsNotNull(responseBase.data);
}
private static void ShouldBeSuccessHasNoData(JsonResultBase? responseBase)
{
Assert.IsTrue(responseBase.success);
Assert.IsNull(responseBase.message);
Assert.IsNull(responseBase.data);
}
private static void {MethodName}ResponseShouldBe(object obj)
{
{responseClass}? data =
JsonConvert.DeserializeObject<{responseClass}>(JsonConvert.SerializeObject(obj));
Assert.IsNotNull(data.Content);
Assert.IsNotNull(data.ContentFileInfo);
Assert.IsNotNull(data.ContentFileInfo);
Assert.IsNotNull(data.ContentFileInfo[0].type);
Assert.IsNotNull(data.ContentFileInfo[0].files);
Assert.IsNotNull(data.ContentFileInfo[0].files[0].id);
Assert.IsNotNull(data.ContentFileInfo[0].files[0].fileName);
Assert.IsNotNull(data.ContentFileInfo[0].files[0].base64);
}
private static void {MethodName}ResponseShouldBeNull(object obj)
{
{responseClass}? data =
JsonConvert.DeserializeObject<{responseClass}>(JsonConvert.SerializeObject(obj));
Assert.IsNotNull(data);
Assert.IsNull(data.Content);
Assert.IsNull(data.ContentFileInfo);
}
[Test]
public async Task {MethodName}_TravelNotes()
{
// Arrange
var url = $"url";
var user = Given{MethodName}Param("TravelNotes", 229, 0);
var body = new StringContent(JsonSerializer.Serialize(user), Encoding.UTF8, "application/json");
GivenAuthToken("token");
// Act
var response = await WhenPost(url, body);
// Assert
ShouldBeSuccessHasNoData(response);
}
[Test]
public async Task {MethodName}_TravelPlan()
{
// Arrange
var url = $"url";
var user = Given{MethodName}Param("TravelPlan", 229, 1);
var body = new StringContent(JsonSerializer.Serialize(user), Encoding.UTF8, "application/json");
GivenAuthToken("token");
// Act
var response = await WhenPost(url, body);
// Assert
ShouldBeSuccessHasNoData(response);
}
private async Task<JsonResultBase?> WhenPost(string url, StringContent body)
{
var response = await _client.PostAsync(url, body);
var content = await response.Content.ReadAsStringAsync();
//Console.Out.WriteLine(content);
JsonResultBase? responseBase = JsonConvert.DeserializeObject<JsonResultBase>(content);
return responseBase;
}
private void GivenAuthToken(string token)
{
_client.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
}
private static RequestClass Given{MethodName}Param(string type, int? id, int? day)
{
var data = new RequestClass();
data.Type = type;
data.Param = new Param() { Id= id, Day = day };
data.ContentFileInfo = new List<string>();
return data;
}
}
Last updated