前提・実現したいこと
ASP.NET MVC5でユニットテストをできるようにプログラムを変更してるのですが、わからなくて困っています。
リポジトリとUnitOfWorkパターンを使用しています。
下記該当コードに記載している部分ですが、
① 任意でTransactionが必要な個所、または直接SQLを使用している箇所があります。
テスト時はcontextを操作しないように変更する必要があるが、どのようにすればよいか。
※現在コントローラーではコンストラクタで、通常時は通常のリポジトリ、ユニットテスト時はダミーリポジトリに切替できるようにしてます。
→ [追記] 任意のトランザクションを設定しても、ユニットテストには影響はないみたいですが、ユニットテストで任意のトランザクション発行のために、DbContextを操作するのは良くない気がします。
[②、③は解決済み]
② ユニットテストでは、コントローラーに設定している[Authorize] をどのように認証させればよいか。
→ Authorizeは影響がなかったため問題ありませんでした。
③ テストのデバッグモードでreturn Json()の前のResponseStatusCodeがユニットテスト時にエラーする
→ MoqでHttpContextを作成し、対応した。
ご教授お願いします。
(参考URL)
・ASP.NET MVC アプリケーションでのリポジトリと作業単位のパターンの実装
https://docs.microsoft.com/ja-jp/aspnet/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
・ASP.NET MVC アプリケーションの単体テストを作成する (C#)
https://docs.microsoft.com/ja-jp/aspnet/mvc/overview/older-versions-1/unit-testing/creating-unit-tests-for-asp-net-mvc-applications-cs
・Creating Unit Testable Applications in ASP.NET MVC - A Beginner's Tutorial
https://www.codeproject.com/Articles/579035/Creating-Unit-Testable-Applications-in-ASP-NET-MVC
該当のソースコード
C#
1// メインプロジェクトのコントローラー(一部抜粋) 2public class DepartmentsController : Controller { 3 private readonly UnitOfWork unitOfWork; 4 5 // Default constructor 6 public DepartmentsController() { 7 this.unitOfWork = new UnitOfWork(); 8 } 9 10 // Unit test use 11 public DepartmentsController(UnitOfWork dummyRepositoryUnitOfWork) { 12 this.unitOfWork = dummyRepositoryUnitOfWork; 13 } 14 15 // Create (コードは省略してます。) 16 public async Task<ActionResult> Create(Department department) { 17 // ... 18 19 /* 問題の箇所 20 using (var dbContextTransaction = unitOfWork.ApplicationDbContext.Database.BeginTransaction()) { 21 await unitOfWork.DepartmentRepository.InsertAsync(department); 22 await unitOfWork.DepartmentRepository.SaveAsync(); 23 await unitOfWork.DepartmentRepository.SortAsync();// SQLで直接順序変更している 24 dbContextTransaction.Commit(); 25 } 26 27 // OkとBadRequestを使い分けしている 28 Response.StatusCode = (int)HttpStatusCode.OK; 29 return Json(new { message : “success” }); 30 */ 31 } 32}
C#
1// メインプロジェクトのUnitOfWorkクラス 2public class UnitOfWork : IDisposable { 3 private readonly ApplicationDbContext context = new ApplicationDbContext(); 4 private IDepartmentRepository departmentRepository; 5 6 // Default constructor 7 public UnitOfWork() { 8 this.departmentRepository = new DepartmentRepository(context); 9 } 10 11 // Test project use 12 public UnitOfWork(IDepartmentRepository dummyDepartmentRepository) { 13 this.departmentRepository = dummyDepartmentRepository; 14 } 15 16 public ApplicationDbContext ApplicationDbContext { 17 get { return this.context; } 18 } 19 20 public IDepartmentRepository DepartmentRepository { get; private set; } 21 22 public void Save() { 23 context.SaveChanges(); 24 } 25 26 private bool disposed = false; 27 28 protected virtual void Dispose(bool disposing) { 29 if (!this.disposed) { 30 if (disposing) { 31 context.Dispose(); 32 } 33 } 34 this.disposed = true; 35 } 36 37 public void Dispose() { 38 Dispose(true); 39 GC.SuppressFinalize(this); 40 } 41 } 42}
C#
1// Testプロジェクトのテストコントローラー(一部抜粋) 2[TestClass] 3public class DepartmentsControllerTest : Controller { 4 private readonly UnitOfWork dummyRepositoryUnitOfWork; 5 private DummyDepartmentRepository dummyDepartmentRepository = null; 6 private DepartmentsController controller = null; 7 8 private List<Department> departments = null; // CollectionAssertを使用するのでList<T>とする 9 10 public DepartmentsControllerTest() { 11 // Create test data 12 departments = new List<Department>(); 13 for (int i = 0; i < 5; i++) { 14 Department department = new Department() { 15 Id = i + 1, 16 DepartmentName = "TEST" + (i + 1) 17 }; 18 19 departments.Add(department); 20 } 21 22 // Create dummy repository ※ダミーリポジトリにテストデータを渡して初期化 23 this.dummyDepartmentRepository = new DummyDepartmentRepository(departments); 24 25 // Create controller with dummy repository unit of work 26 this.dummyRepositoryUnitOfWork = new UnitOfWork(this.dummyDepartmentRepository); 27 this.controller = new DepartmentsController(dummyRepositoryUnitOfWork); 28 } 29 30 [TestMethod] 31 public async Task Create() { 32 // Arrange 33 Department department = new Department { Id = 6, DepartmentName = "TEST6" }; 34 35 // Act 36 await controller.Create(department); 37 IEnumerable<Department> departments = await dummyDepartmentRepository.GetDepartmentsAsync(); 38 List<Department> tempDepartments = departments.ToList(); 39 40 // Assert 41 CollectionAssert.Contains(tempDepartments, department); 42 } 43}
C#
1// Testプロジェクトのダミーリポジトリ(一部抜粋) 2public class DummyDepartmentRepository : IDepartmentRepository { 3 private IList<Department> departments = null; 4 5 public DummyDepartmentRepository(IList<Department> _departments) { 6 this.departments = _departments; 7 } 8 9 public async Task<IEnumerable<Department>> GetDepartmentsAsync() { 10 return departments; 11 } 12 13 public async Task InsertAsync(Department department) { 14 departments.Add(department); 15 } 16 17 public async Task SaveAsync() { 18 // Nothing to do here 19 } 20 21 private bool disposed = false; 22 23 protected virtual void Dispose(bool disposing) {} 24 25 public void Dispose() {} 26}
補足情報(FW/ツールのバージョンなど)
.NET Framework 4.7.2
C#、ASP.NET MVC 5
Visual studio express 2012 for Web
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。