AspectJ可以在第三方库代码中用"new SubclassOfX"替换"new X"吗?

Tho*_*sen 7 aspectj

我正在看AspectJ,看看我们是否可以在我们的测试套件中使用它.

我们有一个相当大的第三方Java通信库硬连线使用它自己的类(它们没有实现任何接口),这反过来意味着我们需要一个物理后端存在并正确配置才能运行测试.

我正在考虑删除此限制的选项.一种可能性是创建麻烦类的子类,然后让AspectJ在加载第三方库时简单地用"new OurSubclassOfX"替换"new X",但我是AspectJ的新手,并且从我的文档简要略读不是典型的用例.

AspectJ能做到这一点吗?配置代码段是什么?

kri*_*aex 9

是的,这是可能的.让我们假设您有一个硬连接类,可能从数据库中获取某些东西,并希望通过一个方面来模拟它:

package de.scrum_master.aop.app;

public class HardWired {
    private int id;
    private String name;

    public HardWired(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public void doSomething() {
        System.out.println("Fetching values from database");
    }

    public int getSomething() {
        return 11;
    }

    @Override
    public String toString() {
        return "HardWired [id=" + id + ", name=" + name + "]";
    }
}
Run Code Online (Sandbox Code Playgroud)

然后有一个小的驱动程序应用程序使用该类(不是接口):

package de.scrum_master.aop.app;

public class Application {
    public static void main(String[] args) {
        HardWired hw = new HardWired(999, "My object");
        System.out.println(hw);
        hw.doSomething();
        System.out.println(hw.getSomething());
    }
}
Run Code Online (Sandbox Code Playgroud)

输出如下:

HardWired [id=999, name=My object]
Fetching values from database
11
Run Code Online (Sandbox Code Playgroud)

现在,您定义了派生的mock类,它应该替换原始类以用于测试目的:

package de.scrum_master.aop.mock;

import de.scrum_master.aop.app.HardWired;

public class HardWiredMock extends HardWired {
    public HardWiredMock(int id, String name) {
        super(id, name);
    }

    @Override
    public void doSomething() {
        System.out.println("Mocking database values");
    }

    @Override
    public int getSomething() {
        return 22;
    }

    @Override
    public String toString() {
        return "Mocked: " + super.toString();
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,您使用简单的切入点和建议来定义一个方面,以在每个构造函数调用期间替换原始值:

package de.scrum_master.aop.aspect;

import de.scrum_master.aop.app.HardWired;
import de.scrum_master.aop.mock.HardWiredMock;


public aspect MockInjector {
    HardWired around(int p1, String p2) : call(HardWired.new(int, String)) && args(p1, p2) {
        return new HardWiredMock(p1, p2);
    }
}
Run Code Online (Sandbox Code Playgroud)

输出根据需要改变:

Mocked: HardWired [id=999, name=My object]
Mocking database values
22
Run Code Online (Sandbox Code Playgroud)

你每个类和构造函数都这样做,并且很好.为了概括该方法,您需要连接点属性,并且根据您想要的距离,可能是反射,但这里非常简单.请享用!

  • 如果您开展工作,请务必将测试框架出售给第三方lib的制作人.祝好运! (2认同)