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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Entity Framework

Entity Frameworkは、.NET Framework 3.5より追加されたデータアクセス技術。正式名称は「ADO.NET Entity Framework」です。データベースエンジンに依存しておらず、データプロバイダの変更のみで様々なデータベースに対応できます。

ASP.NET MVC Framework

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

Q&A

0回答

1248閲覧

EntityFrameworkで、Unitテスト時に手動のTransactionでエラーする

退会済みユーザー

退会済みユーザー

総合スコア0

Entity Framework

Entity Frameworkは、.NET Framework 3.5より追加されたデータアクセス技術。正式名称は「ADO.NET Entity Framework」です。データベースエンジンに依存しておらず、データプロバイダの変更のみで様々なデータベースに対応できます。

ASP.NET MVC Framework

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

0グッド

0クリップ

投稿2020/08/23 00:42

編集2022/01/12 10:55

前提・実現したいこと

ASP.NET MVCのEntityFrameworkで、Model中のEnumのプロパティをNULL許容にすると
Unitテスト時の手動トランザクション(DbContext)でエラーしてしまい困っています。

下記のコードでは、Unitテスト時はトランザクションを設定しても、ダミーリポジトリを使用するようにしているため、DB操作を行わないようにしてます。

usingの時に例外が発生します。型 'System.NullReferenceException' の初回例外が WebApplication.dll で発生しました。
ただし、nullを設定している箇所がないか見直しましたが、見つかりません。

または、他の方法として、ユニットテスト時に、手動のトランザクションをダミーでも実行できればと考えています。

発生している問題・エラーメッセージ

C#

1public class A_Master { 2 public int Id { get; set; } 3 public string name { get; set; } 4 public B_Enum B { get; set; } 5 6 // NULL許容にするとユニットテストの手動トランザクション時にエラーする 7 // public B_Enum? B { get; set; } 8} 9 10public enum B_Enum { 11 B1 = 1, 12 B2 = 2 13} 14 15public class A_MasterController : Controller { 16 private readonly UnitOfWork unitOfWork; 17 18 // Default constructor 19 public A_MasterController() { 20 this.unitOfWork = new UnitOfWork(); 21 } 22 23 // Unit testing use 24 public A_MasterController(UnitOfWork dummyRepositoryUnitOfWork) { 25 this.unitOfWork = dummyRepositoryUnitOfWork; 26 } 27 28 public async Task<ActionResult> Test() { 29 30 // ユニットテスト時に usingのthis.unitOfWork.ApplicationDbContextでエラーする 31 using (var dbContextTransaction = this.unitOfWork.ApplicationDbContext.Database.BeginTransaction()) { 32 // DB操作 33 34 } 35 } 36} 37 38public class UnitOfWork : IDisposable { 39 private readonly ApplicationDbContext context = new ApplicationDbContext(); 40 41 public IA_MasterRepository A_MasterRepository { get; private set; } 42 43 public ApplicationDbContext ApplicationDbContext { 44 get { return this.context; } 45 } 46 47 public UnitOfWork() { 48 this.A_MasterRepository = new A_MasterRepository(context); 49 } 50 51 public UnitOfWork(IA_MasterRepository dummyA_MasterRepository) { 52 this.A_MasterRepository = dummyA_MasterRepository; 53 } 54} 55 56// 【追記】IdentityModelのApplicationDbContext 57public class ApplicationDbContext : IdentityDbContext<ApplicationUser> { 58 public ApplicationDbContext() : base("DefaultConnection", throwIfV1Schema: false) { 59 60 } 61 62 public static ApplicationDbContext Create() { 63 return new ApplicationDbContext(); 64 } 65 66 public DbSet<A_Master> A_Masters { get; set; } 67}

【追記】ユニットテストの状況
・EnumプロパティをNULL許容にしない場合
イメージ説明

・EnumプロパティをNULL許容にした場合、全体(他のテストにも)に影響
イメージ説明

【追記】EnumのNULL許容について
マスタ以外のEnumのNULL許容は問題ありませんでした。
マスタの1モデルのEnumのNULL許容でこの問題が発生していますので、
上記のコードでは再現ができないかもしれません。

一旦、ApplicationDbContextを標準のままに戻し、DbContext用クラスを別に用意しました。

public class TestDbContext : DbContext {
public TestDbContext() : base("TestConnection") { }

public DbSet<A_Master> A_Masters { get; set; }
}

【追記】
ApplicationDbContextを標準のものに戻し、ASP.NET Identity用のデータベースと、通常のModelでデータベースを分けるところまで実施しました。

2つのデータベースと、テーブルを作る部分までは問題ありませんでしたが、
モデルのEnumの部分での変化はありませんでした。

その他に試したこととして、
・モデルを1つにしても、ユニットテスト時に手動トランザクションでエラーがしてました。
・手動トランザクションのエラーがしない状態の時のプロジェクトファイルを、違うパソコンで実行すると手動トランザクションのエラーが発生
・コマンドでのテーブル作成時にはコマンドエラーはしない

他の方法として、ユニットテスト時に、手動のトランザクションをダミーでも実行できればと考えています。

最小構成でモデルを1つにした時でも同様のエラーが出ています。
NullReferenceExceptionは発生しなくなりました。

C#

1public async Task<ActionResult> Create() { 2 // ユニットテスト時、usingの行でエラー 3 using (var dbContextTransaction = this.unitOfWork.TestDbContext.Database.BeginTransaction()) { 4 Debug.WriteLine("Do"); 5 6 dbContextTransaction.Commit(); 7 }; 8 9 /* 10 // ユニットテスト時、UnitOfWorkを使用せず、直接こちらでも実施しても同じエラー 11 // usingの行でエラー 12 var context = new TestSpecificationSystemDbContext(); 13 using (var testContext = context.Database.BeginTransaction()) { 14 Debug.WriteLine("Do"); 15 16 testContext.Commit(); 17 }; 18 */ 19 20 return null; 21}

■ エラー時の出力

txt

1'vstest.executionengine.x86.exe' (CLR v4.0.30319: DefaultDomain): 'C:\WINDOWS\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll' が読み込まれました。シンボルの読み込みをスキップしました。モジュールは最適化されていて、デバッグ オプションの [マイ コードのみ] 設定が有効になっています。 2'vstest.executionengine.x86.exe' (CLR v4.0.30319: DefaultDomain): 'C:\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO 12.0\COMMON7\IDE\COMMONEXTENSIONS\MICROSOFT\TESTWINDOW\vstest.executionengine.x86.exe' が読み込まれました。PDB ファイルを開けないか、ファイルが見つかりません。 3'vstest.executionengine.x86.exe' (CLR v4.0.30319: vstest.executionengine.x86.exe): 'C:\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO 12.0\COMMON7\IDE\COMMONEXTENSIONS\MICROSOFT\TESTWINDOW\Microsoft.VisualStudio.TestPlatform.TestExecutor.Core.dll' が読み込まれました。PDB ファイルを開けないか、ファイルが見つかりません。 4...(省略)

補足情報(FW/ツールのバージョンなど)

.NET Framework 4.7.2
C#、ASP.NET MVC5
Visual Studio Express 2012 for Web

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2020/08/23 03:34 編集

ASP.NET MVC5 も、そのリポジトリやユニットテストなどの独自実装も質問内容からは一切排除して、単純に Entity Framework のコードのみを使って問題を再現できるサンプルは書けないですか? 質問者さん独自の実装の中まで考えなければ分からないような問題は、赤の他人の第三者はあまり興味がわかなくて、回答が得にくいと思いますので。 ApplicationDbContext って何ですか? ASP.NET Identity ベースのユーザー認証を実装すると自動生成される Models/IdentityModels.cs に、IdentityDbContext<TUser> クラスを継承した ApplicationDbContext クラスがあるはずですが、それとバッティングしてませんか?
退会済みユーザー

退会済みユーザー

2020/08/23 04:10

コメントありがとうございます。 問題を再現するコードをすべて載せるのが難しいので、要約して記載させて頂いてます。 ApplicationDbContextは、Models/IdentityModels.cs のものです。 コードを追記させていただきました。 質問の文についてわかりにくくてすみませんが、見直しできるか検討します。
退会済みユーザー

退会済みユーザー

2020/08/23 05:20 編集

質問を書き直されたようですが、タイトルから ASP.NET という言葉が消されただけで、質問の中の ASP.NET 色や独自実装色は全然薄まっておらず、さらには Visual Studio が自動生成する ApplicationDbContext クラスに手を加えて何かわけのわからないことをしているようで、自分にはフォローできそうもないです。 なぜ ApplicationDbContext クラスに public DbSet<A_Master> A_Masters { get; set; } を追加しているのですか? そこがそもそもの間違い(?)のもとで、別にコンテキストクラスを作るべきではないかと思うのですが? そうすれば、かなり ASP.NET 色や独自実装色を薄めた質問にすることができるのでは。
退会済みユーザー

退会済みユーザー

2020/08/23 06:46

タイトルと文章を調整したのみで、EntityFrameworkに限定するものかはわからないのですみませんが。 また、IdentityModel.csの ApplicationDbContext はVS2015の標準テンプレートのもので特に加工していません。 ユーザー情報と、各モデルのテーブルについては同じデータベース上に作成していますので、 コンテキストクラスを分けることは考えていませんでした。 同じデータベースであれば、コンテキストクラスは分けることはできないで合ってますか? 分ける方法があるのであれば教えて頂きたいです。
退会済みユーザー

退会済みユーザー

2020/08/23 21:15 編集

> IdentityModel.csの ApplicationDbContext はVS2015の標準テンプレートのもので特に加工していません。 テンプレートで生成される ApplicationDbContext には public DbSet<A_Master> A_Masters { get; set; } というコードはありません。 質問に書かれたコードのようになっているとすると、「特に加工していません」ということはないはずで、質問者さんが追加した以外にあり得ないですけど? > 同じデータベースであれば、コンテキストクラスは分けることはできないで合ってますか? A_Master テーブルを持つデータベースを別に作れば済む(=コンテキストクラスは分けられる)のではないですか。 そもそも ASP.NET Identity のユーザー情報のストアに使うテーブルを保持するデータベースの中に、ASP.NET Identity 以外が使うテーブルを一緒に入れようという考え方が自分には理解不能です。 自動生成されている App_Start/Startup.Auth.cs のコードを見てください。コメントに「1 要求につき 1 インスタンスのみを使用するように DB コンテキスト、ユーザー マネージャー、サインイン マネージャーを構成します」と書いてあります。 自動生成されるコードがそのようにしているのに、質問者さんが別のところで別の ApplicationDbContext のインスタンスを作って問題ないか・・・なんてことは考えるだけでも時間の無駄では?
退会済みユーザー

退会済みユーザー

2020/08/24 02:32 編集

質問者さん、無言になってしまいましたが、上の私のコメントに対する返答はもらえないのですか? 何も方針変更しないでこのまま進めるのか、私のコメントに沿って見直すのかだけでも返事してください。とにかく無言は NG です。
退会済みユーザー

退会済みユーザー

2020/08/24 12:50 編集

ご指摘の通り、一旦、ApplicationDbContextを標準のままに戻し、DbContext用クラスを別に用意しました。 public class TestDbContext : DbContext { public TestDbContext() : base("TestConnection") { } public DbSet<A_Master> A_Masters { get; set; } } ASP.NET Identity用のデータベースと、通常のModelでデータベースを分けるところまで実施しました。 すみませんが、パッケージマネージャーコンソールのコマンドがわからなかったので、丸一日かかってました。 2つのデータベースと、テーブルを作る部分までは問題ありませんでしたが、 モデルのEnumの部分での変化はありませんでした。 その他に試したこととして、 ・モデルを1つにしても、ユニットテスト時に手動トランザクションでエラーがしてました。 ・手動トランザクションのエラーがしない状態の時のプロジェクトファイルを、違うパソコンで実行すると手動トランザクションのエラーが発生 ・コマンドでのテーブル作成時にはコマンドエラーはしない 他の方法として、ユニットテスト時に、手動のトランザクションをダミーでも実行できればよいのですが、ダミーへの付け替えは難しいでしょうか。やり方を調べても見つかりませんでした。
退会済みユーザー

退会済みユーザー

2020/08/24 23:23 編集

上のコメントのことを質問欄を編集して追記願います。また、最終的なモデルクラスとそれから生成された DB のテーブルのスキーマがどうなっているかも書いてください。 質問者さんの「ユニットテスト」で何をテストして×判定になっているか分かりませんか? 例外発生場所、スローされる例外 NullReferenceException は変わらないのですか?
退会済みユーザー

退会済みユーザー

2020/08/26 09:09

質問者さん、また無言になってしまいましたが・・・ 返事がない=会話ができない=フォローしても時間と労力の無駄になりそう・・・と言うことらしいので、自分は撤退します。悪しからず。
退会済みユーザー

退会済みユーザー

2020/08/26 13:37

ご回答遅くなりすみません。 本文に追記しました。 モデルを1つにして実施してみましたが、エラーはなくなりませんでした。 一旦そのままでいこうと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問