net.projectmonkey.spring.acl.enhancement.identity.strategy.method.DefaultMethodInvocationObjectIdRetrievalStrategyTest.java Source code

Java tutorial

Introduction

Here is the source code for net.projectmonkey.spring.acl.enhancement.identity.strategy.method.DefaultMethodInvocationObjectIdRetrievalStrategyTest.java

Source

package net.projectmonkey.spring.acl.enhancement.identity.strategy.method;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;

import java.lang.reflect.Method;

import net.projectmonkey.spring.acl.enhancement.identity.mapping.SecureObjectMappingWithInternalMethod;
import net.projectmonkey.spring.acl.enhancement.identity.strategy.ExtendedObjectIdentityRetrievalStrategy;
import net.projectmonkey.spring.acl.enhancement.identity.strategy.method.DefaultMethodInvocationObjectIdRetrievalStrategy;
import net.projectmonkey.spring.acl.enhancement.identity.strategy.method.sample.TestClass;
import net.projectmonkey.spring.acl.enhancement.identity.strategy.method.sample.TestClass2;

import org.aopalliance.intercept.MethodInvocation;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.springframework.security.acls.model.ObjectIdentity;
import org.springframework.security.authentication.AuthenticationServiceException;

/*
   Copyright 2012 Andy Moody
       
   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at
       
   http://www.apache.org/licenses/LICENSE-2.0
       
   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

public class DefaultMethodInvocationObjectIdRetrievalStrategyTest {

    private static final String INTERNAL_METHOD = "someInternalMethod";
    private DefaultMethodInvocationObjectIdRetrievalStrategy underTest;
    @Mock
    private ExtendedObjectIdentityRetrievalStrategy mappedIdentityRetrievalStrategy;
    @Mock
    private MethodInvocation invocation;
    @Mock
    private ObjectIdentity identity;

    @Before
    public void setUp() {
        initMocks(this);
        underTest = new DefaultMethodInvocationObjectIdRetrievalStrategy(mappedIdentityRetrievalStrategy);
        underTest.setInternalMethod(INTERNAL_METHOD);
    }

    @Test(expected = AuthenticationServiceException.class)
    public void exceptionThrownIfNoClassProvidedAndSecuredAgainstAnnotationNotPresent()
            throws SecurityException, NoSuchMethodException {
        stubMethodInvocation("methodWithNoSecuredAgainst", null);
        underTest.getObjectIdentity(invocation);
    }

    @Test
    public void nullReturnedIfUsingProcessDomainObjectClassAndNoArgumentsForMethod()
            throws SecurityException, NoSuchMethodException {
        stubMethodInvocation("methodWithNoSecuredAgainst", null);
        underTest.setProcessDomainObjectClass(TestClass.class);
        ObjectIdentity returned = underTest.getObjectIdentity(invocation);
        assertNull(returned);
    }

    @Test
    public void nullReturnedIfUsingSecuredAgainstClassAndNoArgumentsForMethod()
            throws SecurityException, NoSuchMethodException {
        stubMethodInvocation("methodWithSecuredAgainstAndNoParams", null);
        ObjectIdentity returned = underTest.getObjectIdentity(invocation);
        assertNull(returned);
    }

    @Test
    public void nullReturnedWhenNoMatchingParamsExistUsingProcessDomainObjectClass()
            throws SecurityException, NoSuchMethodException {
        stubMethodInvocation("methodWithNoSecuredAgainstAndNoMatchingParams",
                new Class<?>[] { Object.class, Object.class }, new Object(), new Object());
        underTest.setProcessDomainObjectClass(TestClass.class);
        ObjectIdentity returned = underTest.getObjectIdentity(invocation);
        assertNull(returned);
    }

    @Test
    public void nullReturnedWhenNoMatchingParamsExistUsingSecuredAgainstConfig()
            throws SecurityException, NoSuchMethodException {
        stubMethodInvocation("methodWithSecuredAgainstAndNoMatchingParams",
                new Class<?>[] { Object.class, Object.class }, new Object(), new Object());
        ObjectIdentity returned = underTest.getObjectIdentity(invocation);
        assertNull(returned);
    }

    @Test
    public void argumentReturnedWhenSingleParamExistsUsingProcessDomainObjectClass()
            throws SecurityException, NoSuchMethodException {
        final Object arg = new Object();
        stubMethodInvocation("methodWithNoSecuredAgainstAndSingleParam", new Class<?>[] { Object.class }, arg);
        when(mappedIdentityRetrievalStrategy
                .getObjectIdentity(Mockito.isA(SecureObjectMappingWithInternalMethod.class)))
                        .thenAnswer(assertMappingAndReturnIdentity(arg));
        underTest.setProcessDomainObjectClass(TestClass.class);
        ObjectIdentity returned = underTest.getObjectIdentity(invocation);
        assertEquals(identity, returned);
    }

    @Test
    public void argumentReturnedWhenSingleParamExistsUsingSecuredAgainstConfig()
            throws SecurityException, NoSuchMethodException {
        Object arg = new Object();
        stubMethodInvocation("methodWithSecuredAgainstAndSingleParam", new Class<?>[] { Object.class }, arg);
        when(mappedIdentityRetrievalStrategy
                .getObjectIdentity(Mockito.isA(SecureObjectMappingWithInternalMethod.class)))
                        .thenAnswer(assertMappingAndReturnIdentity(arg));
        ObjectIdentity returned = underTest.getObjectIdentity(invocation);
        assertEquals(identity, returned);
    }

    @Test
    public void argumentReturnedWithInternalMethodWhenSecuredIdSingleParamExistsUsingProcessDomainObjectClass()
            throws SecurityException, NoSuchMethodException {
        final Object arg = new Object();
        stubMethodInvocation("methodWithNoSecuredAgainstAndSingleParamWithSecuredId",
                new Class<?>[] { Object.class }, arg);
        when(mappedIdentityRetrievalStrategy
                .getObjectIdentity(Mockito.isA(SecureObjectMappingWithInternalMethod.class)))
                        .thenAnswer(assertMappingAndReturnIdentity(arg, TestClass.class, "someOtherMethod"));
        underTest.setProcessDomainObjectClass(TestClass.class);
        ObjectIdentity returned = underTest.getObjectIdentity(invocation);
        assertEquals(identity, returned);
    }

    @Test
    public void argumentReturnedWithInternalMethodWhenSecuredIdSingleParamExistsUsingSecuredAgainstConfig()
            throws SecurityException, NoSuchMethodException {
        Object arg = new Object();
        stubMethodInvocation("methodWithSecuredAgainstAndSingleParamWithSecuredId", new Class<?>[] { Object.class },
                arg);
        when(mappedIdentityRetrievalStrategy
                .getObjectIdentity(Mockito.isA(SecureObjectMappingWithInternalMethod.class)))
                        .thenAnswer(assertMappingAndReturnIdentity(arg, TestClass.class, "someOtherMethod"));
        ObjectIdentity returned = underTest.getObjectIdentity(invocation);
        assertEquals(identity, returned);
    }

    @Test
    public void argumentReturnedWhenSecuredIdParamsExistUsingProcessDomainObjectClass()
            throws SecurityException, NoSuchMethodException {
        final Object arg = new Object();
        stubMethodInvocation("methodWithNoSecuredAgainstAndParamsWhichMatchBecauseOfSecuredId",
                new Class<?>[] { Object.class, Object.class }, new Object(), arg);
        when(mappedIdentityRetrievalStrategy
                .getObjectIdentity(Mockito.isA(SecureObjectMappingWithInternalMethod.class)))
                        .thenAnswer(assertMappingAndReturnIdentity(arg));
        underTest.setProcessDomainObjectClass(TestClass.class);
        ObjectIdentity returned = underTest.getObjectIdentity(invocation);
        assertEquals(identity, returned);
    }

    @Test
    public void argumentReturnedWhenSecuredIdParamsExistUsingSecuredAgainstConfig()
            throws SecurityException, NoSuchMethodException {
        Object arg = new Object();
        stubMethodInvocation("methodWithSecuredAgainstAndParamsWhichMatchBecauseOfSecuredId",
                new Class<?>[] { Object.class, Object.class }, new Object(), arg);
        when(mappedIdentityRetrievalStrategy
                .getObjectIdentity(Mockito.isA(SecureObjectMappingWithInternalMethod.class)))
                        .thenAnswer(assertMappingAndReturnIdentity(arg));
        ObjectIdentity returned = underTest.getObjectIdentity(invocation);
        assertEquals(identity, returned);
    }

    @Test
    public void argumentReturnedWhenAssignableParamsExistUsingProcessDomainObjectClass()
            throws SecurityException, NoSuchMethodException {
        final TestClass2 arg = new TestClass2();
        stubMethodInvocation("methodWithNoSecuredAgainstAndParamsWhichMatchBecauseOfAssignable",
                new Class<?>[] { Object.class, TestClass.class }, new Object(), arg);
        when(mappedIdentityRetrievalStrategy
                .getObjectIdentity(Mockito.isA(SecureObjectMappingWithInternalMethod.class)))
                        .thenAnswer(assertMappingAndReturnIdentity(arg, TestClass2.class));
        underTest.setProcessDomainObjectClass(TestClass.class);
        ObjectIdentity returned = underTest.getObjectIdentity(invocation);
        assertEquals(identity, returned);
    }

    @Test
    public void argumentReturnedWhenAssignableParamsExistUsingSecuredAgainstConfig()
            throws SecurityException, NoSuchMethodException {
        TestClass2 arg = new TestClass2();
        stubMethodInvocation("methodWithSecuredAgainstAndParamsWhichMatchBecauseOfAssignable",
                new Class<?>[] { Object.class, TestClass.class }, new Object(), arg);
        when(mappedIdentityRetrievalStrategy
                .getObjectIdentity(Mockito.isA(SecureObjectMappingWithInternalMethod.class)))
                        .thenAnswer(assertMappingAndReturnIdentity(arg, TestClass2.class));
        ObjectIdentity returned = underTest.getObjectIdentity(invocation);
        assertEquals(identity, returned);
    }

    @Test
    public void firstSecuredIdParamReturnedEvenIfAssignableParamIsEarlierInTheArgumentList()
            throws SecurityException, NoSuchMethodException {
        TestClass2 arg1 = new TestClass2();
        Object arg2 = new Object();
        Object arg3 = new Object();
        stubMethodInvocation("methodWithMultipleSecuredIdsAndAssignables",
                new Class<?>[] { TestClass.class, Object.class, Object.class }, arg1, arg2, arg3);
        when(mappedIdentityRetrievalStrategy
                .getObjectIdentity(Mockito.isA(SecureObjectMappingWithInternalMethod.class)))
                        .thenAnswer(assertMappingAndReturnIdentity(arg2));
        ObjectIdentity returned = underTest.getObjectIdentity(invocation);
        assertEquals(identity, returned);
    }

    @Test
    public void firstAssignableParamReturnedIfMultipleAssignableParamsExistAndNoSecuredIdParamsArePresent()
            throws SecurityException, NoSuchMethodException {
        TestClass2 arg1 = new TestClass2();
        TestClass2 arg2 = new TestClass2();
        stubMethodInvocation("methodWithMultipleAssignables", new Class<?>[] { TestClass.class, TestClass.class },
                arg1, arg2);
        when(mappedIdentityRetrievalStrategy
                .getObjectIdentity(Mockito.isA(SecureObjectMappingWithInternalMethod.class)))
                        .thenAnswer(assertMappingAndReturnIdentity(arg1, TestClass2.class));
        ObjectIdentity returned = underTest.getObjectIdentity(invocation);
        assertEquals(identity, returned);
    }

    @Test
    public void internalMethodFromSecuredIdAnnotationTakesPrecedenceOverTheInternalMethodConfiguredHere()
            throws SecurityException, NoSuchMethodException {
        TestClass2 arg1 = new TestClass2();
        stubMethodInvocation("methodWithSecuredIdDefiningInternalMethod", new Class<?>[] { TestClass.class }, arg1);
        when(mappedIdentityRetrievalStrategy
                .getObjectIdentity(Mockito.isA(SecureObjectMappingWithInternalMethod.class)))
                        .thenAnswer(assertMappingAndReturnIdentity(arg1, TestClass.class, "someOtherMethod"));
        ObjectIdentity returned = underTest.getObjectIdentity(invocation);
        assertEquals(identity, returned);
    }

    private void stubMethodInvocation(final String methodName, final Class<?>[] parameterTypes,
            final Object... arguments) throws SecurityException, NoSuchMethodException {
        Method method = TestClass.class.getMethod(methodName, parameterTypes);
        when(invocation.getMethod()).thenReturn(method);
        when(invocation.getArguments()).thenReturn(arguments);
    }

    private Answer<ObjectIdentity> assertMappingAndReturnIdentity(final Object expectedDomainObject) {
        return assertMappingAndReturnIdentity(expectedDomainObject, TestClass.class);
    }

    private Answer<ObjectIdentity> assertMappingAndReturnIdentity(final Object expectedDomainObject,
            final Class<?> securedClass) {
        return assertMappingAndReturnIdentity(expectedDomainObject, securedClass, INTERNAL_METHOD);
    }

    private Answer<ObjectIdentity> assertMappingAndReturnIdentity(final Object expectedDomainObject,
            final Class<?> securedClass, final String internalMethod) {
        return new Answer<ObjectIdentity>() {
            @Override
            public ObjectIdentity answer(final InvocationOnMock invocation) throws Throwable {
                Object[] arguments = invocation.getArguments();
                assertEquals(1, arguments.length);
                SecureObjectMappingWithInternalMethod mapping = (SecureObjectMappingWithInternalMethod) arguments[0];
                assertEquals(expectedDomainObject, mapping.getOriginalDomainObject());
                assertEquals(securedClass, mapping.getSecuredClass());
                assertEquals(internalMethod, mapping.getInternalMethod());
                return identity;
            }
        };
    }

}