@Capturing主要用于子类/实现类的Mock
@Capturing平时较少用到,但某些场景下,还非用它不可。 举个例子:通常我们的系统中,都有权限校验。我们通常用AOP来做权限校验,对不?可是AOP生成的类是哪个,连类名都不知道,还怎么Mock? AOP生成的类是动态生成的。可是我们在单元测试时,不希望程序卡在权限校验上(除非是为了测试权限的测试程序)。这种情况下怎么办?用@Capturing ! 看下面的例子!什么测试场景用@Capturing
//权限类,校验用户没有权限访问某资源 public interface IPrivilege { /** * 判断用户有没有权限 * * @param userId * @return 有权限,就返回true,否则返回false */ public boolean isAllow(long userId); }
//@Capturing注解用途 public class CapturingTest { // 测试用户ID long testUserId = 123456l; // 权限检验类,可能是人工写的 IPrivilege privilegeManager1 = new IPrivilege() { @Override public boolean isAllow(long userId) { if (userId == testUserId) { return false; } return true; } }; // 权限检验类,可能是JDK动态代理生成。我们通常AOP来做权限校验。 IPrivilege privilegeManager2 = (IPrivilege) Proxy.newProxyInstance(IPrivilege.class.getClassLoader(), new Class[] { IPrivilege.class }, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) { if ((long) args[0] == testUserId) { return false; } return true; } }); // 有Cautring情形 @Test public void testCaputring(@Capturing IPrivilege privilegeManager) { // 加上了JMockit的API @Capturing, // JMockit会帮我们实例化这个对象,它除了具有@Mocked的特点,还能影响它的子类/实现类 new Expectations() { { // 对IPrivilege的所有实现类录制,假设测试用户有权限 privilegeManager.isAllow(testUserId); result = true; } }; // 不管权限校验的实现类是哪个,这个测试用户都有权限 Assert.assertTrue(privilegeManager1.isAllow(testUserId)); Assert.assertTrue(privilegeManager2.isAllow(testUserId)); } // 没有Cautring情形 @Test public void testWithoutCaputring() { // 不管权限校验的实现类是哪个,这个测试用户没有权限 Assert.assertTrue(!privilegeManager1.isAllow(testUserId)); Assert.assertTrue(!privilegeManager2.isAllow(testUserId)); } }
我们只知道父类或接口时,但我们需要控制它所有子类的行为时,子类可能有多个实现(可能有人工写的,也可能是AOP代理自动生成时)。就用@Capturing。