質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

ユニットテスト

ユニットテストは、システムのテスト手法の一つで、個々のモジュールを対象としたテストの事を指します。対象のモジュールが要求や性能を満たしているか確認する為に実行します。

ASP.NET

ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

ASP.NET MVC Framework

ASP.NET MVC Frameworkは、MVCパターンをベースとした、マイクロソフトのウェブアプリケーション開発用のフレームワークです。

Q&A

解決済

2回答

2479閲覧

ASP.NET MVC5でユニットテストの作り方についてわからなくて困っています。

退会済みユーザー

退会済みユーザー

総合スコア0

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

ユニットテスト

ユニットテストは、システムのテスト手法の一つで、個々のモジュールを対象としたテストの事を指します。対象のモジュールが要求や性能を満たしているか確認する為に実行します。

ASP.NET

ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

ASP.NET MVC Framework

ASP.NET MVC Frameworkは、MVCパターンをベースとした、マイクロソフトのウェブアプリケーション開発用のフレームワークです。

0グッド

0クリップ

投稿2020/07/19 08:33

編集2020/07/20 09:17

前提・実現したいこと

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

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

①任意でTransactionが必要な個所、または直接SQLを使用している箇所があります。
テスト時はcontextを操作しないように変更する必要があるが、どのようにすればよいか。

→ユニットテストに影響しないため、無視とした。

②ユニットテストでは、コントローラーに設定している[Authorize] をどのように認証させればよいか
③テストのデバッグモードでreturn Json()の前のResponseStatusCodeがユニットテスト時にエラーする

→ テストプロジェクトにMockHttpContextを作成し、対応した。

C#

1using Moq; 2using System; 3using System.Collections.Generic; 4using System.Linq; 5using System.Security.Principal; 6using System.Text; 7using System.Threading.Tasks; 8using System.Web; 9 10namespace Test.Tests.Common { 11 12 internal static class MockHttpContext { 13 14 public static Mock<HttpContextBase> getMockHttpContext() { 15 16 var httpContext = new Mock<HttpContextBase>(); 17 18 // Principal 19 GenericIdentity identity = new GenericIdentity("管理者"); 20 GenericPrincipal principal = new GenericPrincipal(identity, new string[] { "Administrator" }); 21 httpContext.SetupGet(e => e.User).Returns(principal); 22 23 // Request 24 var request = new Mock<HttpRequestBase>(); 25 request.SetupGet(e => e.Headers).Returns(new System.Net.WebHeaderCollection { { "X-Requested-With", "XMLHttpRequest" } }); 26 httpContext.SetupGet(e => e.Request).Returns(request.Object); 27 28 // Response 29 var response = new Mock<HttpResponseBase>(); 30 httpContext.SetupGet(x => x.Response).Returns(response.Object); 31 32 return httpContext; 33 } 34 } 35}

投稿2020/08/11 04:19

編集2020/08/11 04:23
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

自己解決しましたので、完了します。
解決方法は後日記載します。

投稿2020/07/22 22:46

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2020/08/11 04:21 編集

自己解決の方法を回答欄に記載
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問