次のような方法があるとします。
public void Method<T>(Func<T> func)
{
...
}
API を使用Expressionして、渡されたコードが実行される前に実行するコードを効果的に挿入する方法はありFuncますか? つまり、私のメソッドでは、実際に を実行するのFuncではなく、それを呼び出すオブジェクトのプロパティを割り当てますFunc。渡されたコードが実行される前に、いくつかのコードを実行したいだけです。Funcまた、渡されたコードが実行されないように、私のコードが から「戻る」ことは可能でしょうか?
編集:OK、それでは不十分だと思いました。これが私がやろうとしていることです。Moles を使用すると、コード内で行われたすべての呼び出しをスタブ化できます。たとえば、次のような静的メソッドを呼び出すテスト不可能なコードがあるとします。
FileSystem.ReadAllText(string fileName);
モルはスタブ/モルオブジェクト(用語が何であれ)を作成し、それを使用してメソッドをスタブアウトできるため、コードが ReadAllText を呼び出すと、私のスタブが呼び出されます。
MFileSytem.ReadAllTextString = s => return "content";
非常にクールなものですが、渡されたパラメーターが特定の値の場合にのみそのメソッドをスタブ化できるように、典型的なモッキング フレームワーク (Moq など) と同様に使用できるように、このアイデアを拡張しようとしています。または、メソッドが一度だけ呼び出されることなどを確認することもできます。これまでのところ、次のとおりです。
まだ非常に荒いです!!
public static class Extensions
{
public static void TestWithMoles<T, U, V>(this T item, Expression<Func<U, V>> expression, MolesDelegates.Func<U, V> stub)
{
var methodCallExpression = expression.Body as MethodCallExpression;
if (methodCallExpression != null)
{
var method = methodCallExpression.Method;
var returnType = method.ReturnType.Name;
var assemblyName = method.DeclaringType.Assembly;
var assmebly = GetMolesAssmeblyName(assemblyName.GetName().Name);
var type = assmebly.GetTypes().FirstOrDefault(t => t.Name == "M" + method.DeclaringType.Name);
var property = type.GetProperties(BindingFlags.Static | BindingFlags.Public).FirstOrDefault(p => p.Name == method.Name + returnType);
property.SetValue(item, stub, null);
}
}
private static Assembly GetMolesAssmeblyName(string assemblyName)
{
var entryAssembly = Assembly.GetExecutingAssembly();
foreach (var assembly in entryAssembly.GetReferencedAssemblies())
{
if (assembly.Name == assemblyName)
{
continue;
}
if (assembly.Name.Contains(assemblyName) && assembly.Name.Contains(".Moles"))
{
return Assembly.Load(assembly.FullName);
}
}
return null;
}
}
今のアイデアは、次のようなクラスがある場合です。
public class TestReader
{
public string Content { get; private set; }
public void LoadFile(string fileName)
{
var content = FileSystem.ReadAllText(fileName);
if (!content.StartsWith("test"))
{
throw new ArgumentException("invalid file");
}
this.Content = content;
}
}
私は今これを行うことができます:
[TestMethod]
[HostType("Moles")]
public void CheckValidFilewithMoles()
{
//arrange
var fileName = "test.txt";
var content = "test";
//act
var test = new TestReader();
test.TestWithMoles<TestReader, string, string>(s => FileSystem.ReadAllText(s), s =>
{
Assert.IsTrue(s == fileName);
return content;
});
test.LoadFile(fileName);
//assert
Assert.AreEqual(content, test.Content);
}
ここまでは順調ですが、まだ何も達成していません。私がやりたいことは、私の拡張メソッドで、これを行うときです:
property.SetValue(item, stub, null);
Molesデリゲートを渡されたものに設定します。渡された値が何であるかを確認できるように、事前にコードを「注入」したいと思います。データを辞書に追加して、メソッド呼び出しの数など
それが今より理にかなっていることを願っています...