1 // ================================================================================================
3 // NUnitテスト支援用クラスソース。</summary>
5 // <copyright file="PrivateAccessor.cs" company="honeplusのメモ帳">
6 // Copyright (C) 2012 Honeplus. All rights reserved.</copyright>
9 // ================================================================================================
11 namespace Honememo.Tests
14 using System.Collections.Generic;
15 using System.Reflection;
16 using NUnit.Framework;
19 /// NUnitでのテスト用に private, protected といった外部からアクセスできないメソッドを実行するためのクラス。
20 /// クラス・オブジェクトに被せるように使用する。
22 /// <typeparam name="T">ラップするオブジェクトのクラス。</typeparam>
23 /// <remarks>使い方については、概ねJUnitのPrivateAccessorと同じようなイメージ。</remarks>
24 public class PrivateAccessor<T>
29 /// オブジェクトを生成する際に使用するコンストラクタ。
31 private ConstructorInfo constructor;
36 private MethodInfo method;
43 /// 指定されたオブジェクトをテストするためのインスタンスを生成。
45 /// <param name="obj">オブジェクト。</param>
46 public PrivateAccessor(T obj)
52 /// 新しいオブジェクトをテストするためのインスタンスを生成。
54 public PrivateAccessor()
63 /// テストする/したクラスのオブジェクト。
76 /// テストするクラスのコンストラクタを指定する。
78 /// <param name="parameterTypes">パラメータ配列。</param>
79 /// <remarks>コンストラクタの確保に失敗した場合は、<see cref="Assert.Fail()"/>にてテストを失敗させる。</remarks>
80 public void SetConstructor(params Type[] parameterTypes)
85 this.constructor = typeof(T).GetConstructor(
86 BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
90 if (this.constructor == null)
93 Assert.Fail("Constructor is not found");
98 // メソッド指定誤り、アクセス不可も含め全てテスト失敗
99 Assert.Fail(e.Message);
104 /// テストするクラスのオブジェクトを指定されたパラメータで生成する。
106 /// <param name="initargs">コンストラクタ呼び出しに引数として渡すオブジェクトの配列。</param>
107 /// <returns>このオブジェクトが表すコンストラクタを呼び出すことで作成される新規オブジェクト。</returns>
109 /// コンストラクタには、<see cref="SetConstructor"/>で指定されたメソッドを用いる。
110 /// 指定されていない場合は、デフォルトコンストラクタを使用する。
111 /// オブジェクトの生成に失敗した場合は、<see cref="Assert.Fail()"/>にてテストを失敗させる。
113 public T NewInstance(params object[] initargs)
117 // コンストラクタが指定されておらず、パラメータも0件の場合
118 if (this.constructor == null
119 && (initargs == null || initargs.Length == 0))
122 this.SetConstructor();
125 // 指定されているコンストラクタでオブジェクトを生成
126 this.Instance = (T)this.constructor.Invoke(initargs);
129 return this.Instance;
131 catch (TargetInvocationException e)
133 // コンストラクタが例外を投げる場合は、そのまま返す
134 throw e.InnerException;
138 // オブジェクトが生成できない場合、テスト失敗
139 Assert.Fail(e.Message);
141 // failの時点で処理は終了する、コンパイルエラー抑止
142 throw new Exception("Accessor error", e);
149 /// <param name="name">メソッドの名前。</param>
150 /// <param name="parameterTypes">パラメータ配列。</param>
151 /// <remarks>メソッドの確保に失敗した場合は、<see cref="Assert.Fail()"/>にてテストを失敗させる。</remarks>
152 public void SetMethod(string name, params Type[] parameterTypes)
157 this.method = typeof(T).GetMethod(
159 BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static,
163 if (this.method == null)
166 Assert.Fail(name + " is not found");
171 // メソッド指定誤り、アクセス不可も含め全てテスト失敗
172 Assert.Fail(e.Message);
177 /// 指定されているメソッドを実行する。
179 /// <param name="args">メソッド呼び出しに使用される引数。</param>
180 /// <returns>このオブジェクトが表すメソッドを、パラメータ<paramref name="args"/>を使用して実行した結果。</returns>
182 /// staticメソッド以外の場合必要な呼び出し元オブジェクトには、
183 /// <see cref="NewInstance"/>または<see cref="Instance"/>
184 /// で指定されたオブジェクトを用いる。
185 /// 指定されていない場合は、可能であればデフォルトコンストラクタでオブジェクトを生成する。
186 /// メソッドの実行に失敗した場合は、<see cref="Assert.Fail()"/>にてテストを失敗させる。
188 public object Invoke(params object[] args)
192 // オブジェクトが指定されておらず、非staticメソッドの場合
193 if (this.Instance == null && !this.method.IsStatic)
195 // デフォルトコンストラクタでオブジェクトを作成する
196 // ※ コンストラクタが指定されている場合、例外
200 // 指定されているオブジェクトでメソッドを実行
201 return this.method.Invoke(this.Instance, args);
203 catch (TargetInvocationException e)
205 // メソッドが例外を投げる場合は、そのまま返す
206 throw e.InnerException;
210 // メソッド未設定、型違いも含めて全てテスト失敗
211 Assert.Fail(e.Message);
213 // failの時点で処理は終了する、コンパイルエラー抑止
214 throw new Exception("Accessor error", e);
219 /// テストする/したクラスのオブジェクトより、指定されたフィールドの値を返す。
221 /// <param name="name">フィールド名。</param>
222 /// <returns>フィールドの値。</returns>
223 /// <remarks>値の取得に失敗した場合は、<see cref="Assert.Fail()"/>にてテストを失敗させる。</remarks>
224 public object GetField(string name)
229 FieldInfo field = typeof(T).GetField(
231 BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
235 Assert.Fail(name + " is not found");
238 // 指定された値をフィールドから取得する
239 return field.GetValue(this.Instance);
243 // フィールド指定誤り、アクセス不可、オブジェクト無しも含め全てテスト失敗
244 Assert.Fail(e.Message);
246 // failの時点で処理は終了する、コンパイルエラー抑止
247 throw new Exception("Accessor error", e);
252 /// テストするクラスのオブジェクトで、指定されたフィールドに値を設定する。
254 /// <param name="name">フィールド名。</param>
255 /// <param name="value">新しいフィールド値。</param>
257 /// staticフィールド以外の場合に必要な設定先オブジェクトには、
258 /// <see cref="NewInstance"/>または<see cref="Instance"/>
259 /// で指定されたオブジェクトを用いる。
260 /// 指定されていない場合は、可能であればデフォルトコンストラクタでオブジェクトを生成する。
261 /// 値の設定に失敗した場合は、<see cref="Assert.Fail()"/>にてテストを失敗させる。
263 public void SetField(string name, object value)
268 FieldInfo field = typeof(T).GetField(
270 BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
274 Assert.Fail(name + " is not found");
277 // オブジェクトが指定されておらず、非staticフィールドの場合
278 if (this.Instance == null && !field.IsStatic)
280 // デフォルトコンストラクタでオブジェクトを作成する
281 // ※ コンストラクタが指定されている場合、例外
286 field.SetValue(this.Instance, value);
290 // フィールド指定誤り、アクセス不可も含め全てテスト失敗
291 Assert.Fail(e.Message);
296 /// テストする/したクラスのオブジェクトより、指定されたプロパティの値を返す。
298 /// <param name="name">プロパティ名。</param>
299 /// <param name="index">インデックスプロパティの場合のインデックス。</param>
300 /// <returns>プロパティの値。</returns>
301 /// <remarks>値の取得に失敗した場合は、<see cref="Assert.Fail()"/>にてテストを失敗させる。</remarks>
302 public object GetProperty(string name, params object[] index)
307 PropertyInfo property = typeof(T).GetProperty(
309 BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
310 if (property == null)
313 Assert.Fail(name + " is not found");
316 // 指定された値をプロパティから取得する
317 return property.GetValue(this.Instance, index);
321 // プロパティ指定誤り、アクセス不可、オブジェクト無しも含め全てテスト失敗
322 Assert.Fail(e.Message);
324 // failの時点で処理は終了する、コンパイルエラー抑止
325 throw new Exception("Accessor error", e);
330 /// テストするクラスのオブジェクトで、指定されたプロパティに値を設定する。
332 /// <param name="name">プロパティ名。</param>
333 /// <param name="value">新しいプロパティ値。</param>
334 /// <param name="index">インデックスプロパティの場合のインデックス。</param>
336 /// 設定先オブジェクトには<see cref="NewInstance"/>または<see cref="Instance"/>
337 /// で指定されたオブジェクトを用いる。
338 /// 指定されていない場合は、可能であればデフォルトコンストラクタでオブジェクトを生成する。
339 /// 値の設定に失敗した場合は、<see cref="Assert.Fail()"/>にてテストを失敗させる。
341 public void SetProperty(string name, object value, params object[] index)
346 PropertyInfo property = typeof(T).GetProperty(
348 BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
349 if (property == null)
352 Assert.Fail(name + " is not found");
356 if (this.Instance == null)
358 // デフォルトコンストラクタでオブジェクトを作成する
359 // ※ コンストラクタが指定されている場合、例外
364 property.SetValue(this.Instance, value, index);
366 catch (TargetInvocationException e)
368 // メソッドが例外を投げる場合は、そのまま返す
369 throw e.InnerException;
373 // プロパティ指定誤り、アクセス不可も含め全てテスト失敗
374 Assert.Fail(e.Message);