如何在单元测试中调用Postsharp Aspect?
How to call Postsharp Aspect in Unit Test?
我有一个方面排序列表。
public override void OnInvoke(MethodInterceptionArgs args)
{
args.Proceed();
var string_list = (args.ReturnValue as List<string>);
string_list.Sort();
Console.WriteLine("Postsharp Aspect içerisinde sıralanan koleksiyon: ");
foreach (var item in string_list)
{
Console.WriteLine(item);
}
}
我有一个返回列表的方法。
[PostSharpExecuteAfterMethod]
public virtual List<string> Liste_Döndür()
{
List<string> liste = new List<string>();
liste.Add("g");
liste.Add("b");
liste.Add("hjh");
liste.Add("a");
Console.WriteLine("Method'dan dönen string liste: ");
foreach (var item in liste)
{
Console.WriteLine(item);
}
return liste;
}
这是我的测试方法。
public class SomeClass
{
[PostSharpExecuteAfterMethod]
public virtual List<string> GimmeSomeData()
{
throw new NotImplementedException();
}
}
[TestClass]
public class UnitTest1
{
[TestMethod]
//[PostSharpExecuteAfterMethod]
public void TestMethod1()
{
var mock = new Mock<SomeClass>();
mock.Setup(m => m.GimmeSomeData()).Returns(() => new List<string> { "1", "2", "3" });
//liste
var resultList = mock.Object.GimmeSomeData();
}
}
所以,我想使用 Moq 在我的测试方法中调用我的方面。每当我尝试创建一个模拟的 class 之类的东西时。它没有用。我怎样才能做到这一点?
由于目标方法上拦截的顺序,您的代码示例中的方面未被调用。模拟拦截器添加在 PostSharp 拦截器之前,因此它 returns PostSharp 方面有机会执行之前的结果。
在大多数情况下,这是所需的行为。您可以将方面视为方法中的附加代码。因此,您自己的代码和应用方面应作为一个单元进行测试。
如果您的用例要求您在测试期间将方面和原始方法体分开,那么您需要确保在 PostSharp 方面之后调用模拟拦截器。您可以在下面找到一个示例 MockAspect
来实现这一点:
public interface IMockable<T> where T : class
{
Mock<T> CreateMock();
}
[Conditional( "DEBUG" )] // Exclude mocking interceptor in release builds.
public class MockAspect : TypeLevelAspect, IAspectProvider
{
public IEnumerable<AspectInstance> ProvideAspects( object targetElement )
{
Type targetType = (Type) targetElement;
yield return new AspectInstance( targetElement, (IAspect) Activator.CreateInstance( typeof( MockAspectImpl<> ).MakeGenericType( targetType ) ) );
}
}
[PSerializable]
// Make sure we are ordered after our aspect PostSharpExecuteAfterMethod.
[AspectTypeDependency(AspectDependencyAction.Order, AspectDependencyPosition.After, typeof( PostSharpExecuteAfterMethod ))]
public class MockAspectImpl<T> : IInstanceScopedAspect, IAdviceProvider, IMockable<T> where T : class
{
[PNonSerialized]
private Mock<T> mock;
public object CreateInstance( AdviceArgs adviceArgs )
{
return new MockAspectImpl<T>();
}
public void RuntimeInitializeInstance()
{
}
public IEnumerable<AdviceInstance> ProvideAdvices( object targetElement )
{
yield return new IntroduceInterfaceAdviceInstance( typeof( IMockable<T> ) );
}
Mock<T> IMockable<T>.CreateMock()
{
this.mock = new Mock<T>();
return this.mock;
}
[OnMethodInvokeAdvice]
[MulticastPointcut( Targets = MulticastTargets.Method,
Attributes = MulticastAttributes.Instance | MulticastAttributes.Public | MulticastAttributes.Virtual )]
public void OnMethodInvoke( MethodInterceptionArgs args )
{
if ( this.mock != null )
{
args.ReturnValue = args.Method.Invoke( mock.Object, args.Arguments.ToArray() );
}
else
{
args.Proceed();
}
}
}
接下来您可以将 MockAspect
应用于您的目标 class:
[MockAspect]
public class SomeClass
{
[PostSharpExecuteAfterMethod]
public virtual List<string> GimmeSomeData()
{
throw new NotImplementedException();
}
}
这就是您如何使用在方面之后调用的模拟:
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var obj = new SomeClass();
var mock = ( (IMockable<SomeClass>) obj ).CreateMock();
mock.Setup( m => m.GimmeSomeData() ).Returns( () => new List<string> { "3", "1", "2" } );
var resultList = obj.GimmeSomeData();
Console.WriteLine( "Result: {0}", string.Join( ", ", resultList ) );
}
}
我有一个方面排序列表。
public override void OnInvoke(MethodInterceptionArgs args)
{
args.Proceed();
var string_list = (args.ReturnValue as List<string>);
string_list.Sort();
Console.WriteLine("Postsharp Aspect içerisinde sıralanan koleksiyon: ");
foreach (var item in string_list)
{
Console.WriteLine(item);
}
}
我有一个返回列表的方法。
[PostSharpExecuteAfterMethod]
public virtual List<string> Liste_Döndür()
{
List<string> liste = new List<string>();
liste.Add("g");
liste.Add("b");
liste.Add("hjh");
liste.Add("a");
Console.WriteLine("Method'dan dönen string liste: ");
foreach (var item in liste)
{
Console.WriteLine(item);
}
return liste;
}
这是我的测试方法。
public class SomeClass
{
[PostSharpExecuteAfterMethod]
public virtual List<string> GimmeSomeData()
{
throw new NotImplementedException();
}
}
[TestClass]
public class UnitTest1
{
[TestMethod]
//[PostSharpExecuteAfterMethod]
public void TestMethod1()
{
var mock = new Mock<SomeClass>();
mock.Setup(m => m.GimmeSomeData()).Returns(() => new List<string> { "1", "2", "3" });
//liste
var resultList = mock.Object.GimmeSomeData();
}
}
所以,我想使用 Moq 在我的测试方法中调用我的方面。每当我尝试创建一个模拟的 class 之类的东西时。它没有用。我怎样才能做到这一点?
由于目标方法上拦截的顺序,您的代码示例中的方面未被调用。模拟拦截器添加在 PostSharp 拦截器之前,因此它 returns PostSharp 方面有机会执行之前的结果。
在大多数情况下,这是所需的行为。您可以将方面视为方法中的附加代码。因此,您自己的代码和应用方面应作为一个单元进行测试。
如果您的用例要求您在测试期间将方面和原始方法体分开,那么您需要确保在 PostSharp 方面之后调用模拟拦截器。您可以在下面找到一个示例 MockAspect
来实现这一点:
public interface IMockable<T> where T : class
{
Mock<T> CreateMock();
}
[Conditional( "DEBUG" )] // Exclude mocking interceptor in release builds.
public class MockAspect : TypeLevelAspect, IAspectProvider
{
public IEnumerable<AspectInstance> ProvideAspects( object targetElement )
{
Type targetType = (Type) targetElement;
yield return new AspectInstance( targetElement, (IAspect) Activator.CreateInstance( typeof( MockAspectImpl<> ).MakeGenericType( targetType ) ) );
}
}
[PSerializable]
// Make sure we are ordered after our aspect PostSharpExecuteAfterMethod.
[AspectTypeDependency(AspectDependencyAction.Order, AspectDependencyPosition.After, typeof( PostSharpExecuteAfterMethod ))]
public class MockAspectImpl<T> : IInstanceScopedAspect, IAdviceProvider, IMockable<T> where T : class
{
[PNonSerialized]
private Mock<T> mock;
public object CreateInstance( AdviceArgs adviceArgs )
{
return new MockAspectImpl<T>();
}
public void RuntimeInitializeInstance()
{
}
public IEnumerable<AdviceInstance> ProvideAdvices( object targetElement )
{
yield return new IntroduceInterfaceAdviceInstance( typeof( IMockable<T> ) );
}
Mock<T> IMockable<T>.CreateMock()
{
this.mock = new Mock<T>();
return this.mock;
}
[OnMethodInvokeAdvice]
[MulticastPointcut( Targets = MulticastTargets.Method,
Attributes = MulticastAttributes.Instance | MulticastAttributes.Public | MulticastAttributes.Virtual )]
public void OnMethodInvoke( MethodInterceptionArgs args )
{
if ( this.mock != null )
{
args.ReturnValue = args.Method.Invoke( mock.Object, args.Arguments.ToArray() );
}
else
{
args.Proceed();
}
}
}
接下来您可以将 MockAspect
应用于您的目标 class:
[MockAspect]
public class SomeClass
{
[PostSharpExecuteAfterMethod]
public virtual List<string> GimmeSomeData()
{
throw new NotImplementedException();
}
}
这就是您如何使用在方面之后调用的模拟:
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var obj = new SomeClass();
var mock = ( (IMockable<SomeClass>) obj ).CreateMock();
mock.Setup( m => m.GimmeSomeData() ).Returns( () => new List<string> { "3", "1", "2" } );
var resultList = obj.GimmeSomeData();
Console.WriteLine( "Result: {0}", string.Join( ", ", resultList ) );
}
}