如何对PostSharp方面进行单元测试?

13
在询问了关于使用PostSharp实现方面的question之后,我想到未来可能需要更新此方面的代码,而且我不想冒破坏一切的风险。因此,我开始考虑单元测试。我的第一个问题是:是否有必要考虑对一个方面进行单元测试?我希望答案是“是”,但如果不是,我希望得到其他建议。然后,如果是这样的话,如何为PostSharp方面实现单元测试?请注意,保留html标记。
2个回答

10

在单元测试中测试方面确实是有意义的,因为它们代表功能,并且由于您在多个地方使用它,因此测试它变得更加重要。

但是您必须将其分为两部分:

  1. 测试实际方面的功能
  2. 测试用于实际执行方面功能的上下文提取是否正常工作

对于第一部分,如果您已将实际功能与执行方面功能的属性解耦,则创建单元测试与单元测试常规代码没有区别。

对于第二部分,您还需要解耦上下文提取,这可能看起来有些杀鸡焉用牛刀,但如果您想正确地进行单元测试,就需要做这件事情。

在这个过程中,您还应该利用编译时验证,它可以防止您以错误的方式使用属性。有时需要测试某些无法用属性语法描述的条件,这时就需要使用编译时验证。对我来说,这非常有帮助,大大减少了关于PostSharp方面的调试会话数量,详情请参见:
http://www.sharpcrafters.com/postsharp/robustness

以下是一些非常基本的示例代码,没有任何依赖注入,只是为了说明如何将事情拆分:

public sealed class TraceAttribute : OnMethodBoundaryAspect
{
    private readonly string category;
    private TraceArgumentService argumentService;
    private TraceService traceService;

    public string Category { get { return category; } }

    public TraceAttribute(string category)
    {
        this.category = category;
    }

    public override void RuntimeInitialize(System.Reflection.MethodBase method)
    {
        base.RuntimeInitialize(method);
        this.argumentService = new TraceArgumentService();
        this.traceService = new TraceService();
    }


    public override void OnEntry(MethodExecutionArgs args)
    {                
        traceService.Write(
            argumentService.GetDeclaringTypeName(args),
            argumentService.GetMethodName(args),
            category);

    }
}

public class TraceArgumentService
{
    public string GetDeclaringTypeName(MethodExecutionArgs args)
    {
        return args.Method.DeclaringType.Name;
    }

    public string GetMethodName(MethodExecutionArgs args)
    {
        return args.Method.Name;
    }
}

public class TraceService
{
    public void Write(string declaringTypeName, string methodName, string category)
    {
        Trace.WriteLine(string.Format("Entering {0}.{1}.",
            declaringTypeName, methodName), category);
    }
}

你可能会问为什么要使用TraceService和单独的TraceArgumentService

  • 跟PostSharp无关的跟踪逻辑,不应该知道MethodExecutionArgs
  • MethodExecutionArgs中提取参数并不是跟踪的一部分,它更多地与方面相关。由于您希望能够对其进行测试,因此需要以某种方式将其分离。

我完全同意你的“第一部分”。关于你的“第二部分”,我正在寻找代码示例,以便了解“它会是什么样子”,因为这是我的问题的关键点。我将根据你的建议研究编译时验证。 - remio
1
@remio 我已经更新了我的答案,并提供了如何将不同的任务分离以使它们易于测试的示例。 - ntziolis
我懂了。解耦是关键。非常感谢您提供的明确示例。 - remio


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接