はじめに
最近参加してるPJで初めてがっつりC#をかくことになりました。
その中でUnitテストもお願いね~と言われました。
今回は初めてなりにやってみた備忘録。
環境
- VisualStudio2019
- ASP.NET Core
xUnitテストの始め方
こちらのサイトを参考に作っていきました。
書き方がまとまっていてわかりやすかったです。
今回やってみたこと備忘録
データベースの値が正しく更新されているか確認したい…
- インメモリDBにテストデータを登録してテストすればいい
EntityFrameworkCoreで提供されているインメモリDBを使いました。
インメモリDBとはメモリをデータ保存領域とした、データベースプロバイダです。
先輩のコードをまねして作っていた私はどこにデータが登録されているのかわからず、
ずっと接続先の設定が悪いと思ってました。
実際にかいたコードは以下のとおり
using System;
using Xunit;
using Microsoft.EntityFrameworkCore;
namespace Tests
{
public class MyDbContextFixture : IDisposable
{
public DbContextOptions<MyDBContextName> Options;
public MyDBContextName Context;
public MyDbContextFixture ()
{
Options = new DbContextOptionsBuilder<MyDBContextName>()
.UseInMemoryDatabase(databaseName: "MyDatabaseName")
.Options;
Context = new MyDBContextName(Options);
}
public void Dispose()
{
Context.Dispose();
}
}
テストコードはこちら。
内容は、データベースに登録したステータスコードが60に更新されるかを確認するものです。
テストしたいメソッドの返却値が更新対象のIDのみを返却するので、
そのIDをもとに再検索をかけて確認しています。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xunit;
using Xunit.Abstractions;
using Newtonsoft.Json;
// テストしたいプロジェクトを参照するのを忘れずに
namespace Tests.Functions
{
/// <summary>
/// <see cref="Function{TDbContext}">のテストクラス
/// </summary>
public class FunctionTest : IClassFixture<MyDbContextFixture>, IDisposable
{
private readonly ITestOutputHelper _output;
private readonly MyDbContextFixture _fixture;
private readonly MyDBContextName _context;
public FunctionTest(MyDbContextFixture fixture, ITestOutputHelper output)
{
_output = output;
_fixture = fixture;
_context = fixture.Context;
}
// ご自身で引数のテストデータ作成します
// DBに登録したいテストデータをいれます
// GetTestData()
/// <summary>
/// テストデータを削除
/// </summary>
void IDisposable.Dispose()
{
var list = _context.PrPrint.ToList<PrPrint>();
_context.PrPrint.RemoveRange(list);
_context.SaveChanges();
}
/// <summary>
/// ステータスコードが60から70に更新
/// </summary>
[Theory(DisplayName = "ステータスコード更新")]
[MemberData(nameof(MyTestDataName))]
public void UpdateTest(inputModel)
{
var function = new TestFunction<MyDBContextName>(_context);
// テストデータをInsert
var list = GetTestData();
_context.TestTable.AddRange(GetTestData());
_context.SaveChanges();
// テストしたい内容
var result = function.Update_Test(inputModel);
_output.WriteLine(JsonConvert.SerializeObject(result));
var entity = _context.TestTable.Where(x => x.Id == result.Id).SingleOrDefault();
// DBのステータスコードが70
Assert.Equal("70", entity.StatusCd);
}
}
}
例外の種類とメッセージが正しいか確認したい…
- Assert.Throwsで例外情報を取得。その後に、Assert.Equalなどでメッセージとの整合性を確認。
/// <summary>
/// ステータスコードが69
/// </summary>
[Theory(DisplayName = "ステータスコード更新")]
[MemberData(nameof(MyTestDataName))]
public void UpdateError(TestModel inputModel)
{
var function = new TestFunction<MyDBContextName>(_context);
// テストデータをInsert
var list = GetTestData();
_context.PrPrint.AddRange(GetTestData());
_context.SaveChanges();
var ex = Assert.Throws<ApplicationException>(() =>
{
function.Update_Test(inputModel);
});
Assert.IsType<ApplicationException>(ex);
Assert.Equal("状態69であるデータの更新はできません", ex.Message);
}
やってみて
インメモリDBは割とテストに使えて便利だなと思いました。
今回初めてプロジェクト内でテストコードをがっつり書いたのですが、
テストコードを書くのに一苦労という感じでした。
でも、テストのデバック実行もできるので、今後使いこなしていきたいなという印象です。
今後また先輩から得た知識を備忘録として追記していく予定です。