gpt4 book ai didi

c# - 使用 AOP/PostSharp 进行单元测试

转载 作者:太空狗 更新时间:2023-10-30 00:53:17 26 4
gpt4 key购买 nike

我正在尝试使用 PostSharp 实现安全方面,以便在我的存储库层中应用方法级授权检查。

概念概述here .

然而,这些授权检查在单元测试期间受到阻碍,使它们更多地进入集成测试。

将这些隔离为单元测试的最佳方法是什么,本质上是忽略/模拟安全方面,这样我就可以只测试实际的类行为,而无需初始化一堆安全信息?

AOP 是否与单元测试存在内在冲突?

最佳答案

首先回答您的第二个问题,不,AOP 与单元测试没有本质上的冲突。通常我会说最好分别对方法和方面进行单元测试。

对于您的情况,有多种选择。

最简单的方法就是让单元测试设置方法确保线程具有所需的权限。

如果您不想这样做,可以通过两种方法将单元测试分开。第一种是从您应用安全方面的方法中将所有代码提取到单独的方法中,如下所示:

[SecurityAspect]
void DoSomething()
{
DoSomethingInternal();
}

void DoSomethingInternal()
{
// this is the real code
}

然后您可以针对所有不安全的“内部”方法运行单元测试——测试其中的逻辑而不用担心安全性。

第二种方法是将模拟权限测试器注入(inject)方面本身。为了能够做到这一点,您必须定义一个单独的类和接口(interface)来执行测试安全性的实际逻辑,就像这样(假设它是您传入的线程以验证安全性):

public interface IPermissionsChecker
{
bool HasPermissions(Thread thread);
}

这是您的实时系统的权限检查器:

public class RealPermissionsChecker : IPermissionsChecker
{

public bool HasPermissions(Thread thread)
{
// do your real work here
}
}

这是您将在单元测试中使用的那个

public class MockPermissionsChecker : IPermissionsChecker
{
public bool HasPermissions(Thread thread)
{
return true;
}
}

现在你需要像这样定义你的方面:

public class SecurityChecker : OnMethodBoundaryAspect
{

IPermissionsChecker _checker;

public override void OnEntry(MethodExecutionArgs args)
{
if (!_checker.HasPermissions(Thread.CurrentThread))
throw new SecurityException("No permissions");
}
}

唯一剩下的问题是需要将正确的权限检查器注入(inject)方面。

我之前做过的有点老套的方法是让 _checker 成为一个静态字段,并提供一个静态方法来初始化它:

public class SecurityChecker : OnMethodBoundaryAspect
{

private static IPermissionsChecker _checker;

public static void InjectChecker(IPermissionsChecker checker)
{
// best put some code here to make sure this is only called once,
// as well as doing thread synchronization
if (_checker == null)
_checker = checker;
}

InjectChecker 是静态的这一事实意味着您可以从应用程序启动(或单元测试启动)代码访问它。我怀疑单元测试纯粹主义者会对此皱眉——你必须确保在应用程序启动时调用它,但我认为这是将检查器注入(inject)方面的最简单方法,避免了你的其余代码的事实无法直接访问方面的实例。

更复杂的替代方法是在您的方面覆盖 RunTimeInitialize() - 在初始化方面时,PostSharp 会调用此方法。你可能会这样做:

    public override void RuntimeInitialize(MethodBase method)
{
base.RuntimeInitialize();
this._checker =PermissionsCheckerProvider.Current.GetChecker();
}

您会看到这需要您定义另一个类:

public class PermissionsCheckerProvider
{
// make sure you set this at app startup, either to the mock or to the real checker
public static PermissionsCheckerProvider Current { get; set;}

public IPermissionsChecker GetChecker()
{
}
}

这种方法保证该方法将在正确的时间尝试初始化,但是您会遇到一个问题,即在方面尝试初始化之前确保您已经提供了适当的当前提供者。因此,我个人可能会选择第一种方法来使事情变得简单。

这里有一些关于依赖注入(inject)和 RuntimeInitialize 的讨论。 https://codereview.stackexchange.com/questions/20341/inject-dependency-into-postsharp-aspect

关于c# - 使用 AOP/PostSharp 进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16987385/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com