如何在单元测试中调用后锐方面?

问题描述 投票:2回答:1

我有一个方面排序列表。

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在测试方法中调用我的方面。每当我尝试创建模拟类或其他东西时。没用我怎样才能做到这一点?

c# unit-testing postsharp aspect
1个回答
0
投票

由于目标方法上侦听的顺序,因此未调用代码示例中的方面。模拟拦截器在PostSharp拦截器之前添加,因此它在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应用于您的目标班级:

[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 ) );
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.