问题 测试Spring AOP方面


在编写方面时,如何测试它们是否匹配以及在我需要时调用它们?

我在用着 @Aspect Spring 2.5.6的声明。


我不关心功能,否则提取和测试。


12104
2017-08-09 12:49


起源



答案:


这里要测试三种不同的东西:

  1. 你的切入点符合你的期望吗?
  2. 您的建议是否参考了正确的切入点?
  3. 建议是否按预期进行?

要测试切入点,您可以定义一些与预期“真实”目标具有相同包/类型/方法签名的测试类型,然后针对切入点定义测试建议以确保它们匹配(还定义了一些不应该的类型)匹配以确保切入点不太自由)。我通常通过定义建议来对测试目标中的方法进行回调,设置标志,然后断言标志已设置。

测试建议比较棘手。我倾向于将所有建议体委托给普通方法,然后专注于测试方法而不是建议。

如果您已经这样做了,唯一缺少的部分是您的建议应用于正确的切入点并实际调用方法。如果你担心这可能是一个问题,你可以通过创建来做到这一点 另一个 与您的通知执行匹配的方面,并设置一个标志以显示方面调用的预期委托方法,并覆盖该方法以不执行任何操作。


8
2017-08-09 13:04





我最终通过以下方式创建了一些集成测试的东西:

创建了一个Spring感知的JUnit测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "aspects-test.xml" })
public class SomeAspectTest {

}

为此测试创建了弹簧配置:

  • 启用@AspectJ用法;
  • 使用虚拟依赖项配置我的方面
  • 声明应该由方面拾取的bean

    <aop:aspectj-autoproxy />
    <bean class="SomeAspect">
        <property name="userDetailsSource">
                <bean class="StubUserDetailsSource"/>
        </property>
    </bean>
    <bean class="DummyService"/>
    

在单元测试中,我检索虚拟服务并调用其方法

@Autowired
private DummyService _dummyService;

@Test(expected = ApplicationSecurityException.class)
public void adminOnlyFails() throws ApplicationSecurityException {

    _dummyService.adminOnly();
}

7
2017-10-17 21:05



你能提供更多细节吗? - Javatar
我认为,当这么多逻辑实际上是运行时生成时,创建半集成测试是正常的。 - Gepsens
因此,您调用一个应该调用方面方法的方法,但是您从未回答过如何验证是否正在调用方面方法。 @Javatar我认为这是你要找的细节?我猜你的示例方面总是抛出ApplicationSecurityException?合法的方法调用怎么样? - Jorge
@Jorge - 我会像在常规的JUnit测试中一样验证方法。这个测试失败。对于不应该失败的测试,我会删除 expected 属性。或验证返回码。最后,它只是一个简单的JUnit测试。 - Robert Munteanu


答案:


这里要测试三种不同的东西:

  1. 你的切入点符合你的期望吗?
  2. 您的建议是否参考了正确的切入点?
  3. 建议是否按预期进行?

要测试切入点,您可以定义一些与预期“真实”目标具有相同包/类型/方法签名的测试类型,然后针对切入点定义测试建议以确保它们匹配(还定义了一些不应该的类型)匹配以确保切入点不太自由)。我通常通过定义建议来对测试目标中的方法进行回调,设置标志,然后断言标志已设置。

测试建议比较棘手。我倾向于将所有建议体委托给普通方法,然后专注于测试方法而不是建议。

如果您已经这样做了,唯一缺少的部分是您的建议应用于正确的切入点并实际调用方法。如果你担心这可能是一个问题,你可以通过创建来做到这一点 另一个 与您的通知执行匹配的方面,并设置一个标志以显示方面调用的预期委托方法,并覆盖该方法以不执行任何操作。


8
2017-08-09 13:04





我最终通过以下方式创建了一些集成测试的东西:

创建了一个Spring感知的JUnit测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "aspects-test.xml" })
public class SomeAspectTest {

}

为此测试创建了弹簧配置:

  • 启用@AspectJ用法;
  • 使用虚拟依赖项配置我的方面
  • 声明应该由方面拾取的bean

    <aop:aspectj-autoproxy />
    <bean class="SomeAspect">
        <property name="userDetailsSource">
                <bean class="StubUserDetailsSource"/>
        </property>
    </bean>
    <bean class="DummyService"/>
    

在单元测试中,我检索虚拟服务并调用其方法

@Autowired
private DummyService _dummyService;

@Test(expected = ApplicationSecurityException.class)
public void adminOnlyFails() throws ApplicationSecurityException {

    _dummyService.adminOnly();
}

7
2017-10-17 21:05



你能提供更多细节吗? - Javatar
我认为,当这么多逻辑实际上是运行时生成时,创建半集成测试是正常的。 - Gepsens
因此,您调用一个应该调用方面方法的方法,但是您从未回答过如何验证是否正在调用方面方法。 @Javatar我认为这是你要找的细节?我猜你的示例方面总是抛出ApplicationSecurityException?合法的方法调用怎么样? - Jorge
@Jorge - 我会像在常规的JUnit测试中一样验证方法。这个测试失败。对于不应该失败的测试,我会删除 expected 属性。或验证返回码。最后,它只是一个简单的JUnit测试。 - Robert Munteanu