package org.springframework.roo.addon.layers.service;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.springframework.roo.addon.layers.service.ServiceLayerMethod.FIND_ALL;
import static org.springframework.roo.addon.layers.service.ServiceLayerMethod.FIND_ENTRIES;
import static org.springframework.roo.addon.layers.service.ServiceLayerMethod.SAVE;
import static org.springframework.roo.addon.layers.service.ServiceLayerMethod.UPDATE;
import java.util.Arrays;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.roo.addon.plural.PluralMetadata;
import org.springframework.roo.classpath.TypeLocationService;
import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetails;
import org.springframework.roo.classpath.layers.MemberTypeAdditions;
import org.springframework.roo.classpath.layers.MethodParameter;
import org.springframework.roo.metadata.MetadataService;
import org.springframework.roo.model.JavaType;
import org.springframework.roo.project.Path;
/**
* Unit test of {@link ServiceLayerProvider}
*
* @author Andrew Swan
* @since 1.2.0
*/
public class ServiceLayerProviderTest {
private static final String BOGUS_METHOD = "bogus";
private static final String CALLER_MID = "MID:anything#com.example.web.PersonController";
private static final String SERVICE_MID = "MID:anything#com.example.serv.PersonService";
private static final MethodParameter SIZE_PARAMETER = new MethodParameter(
JavaType.INT_PRIMITIVE, "count");
private static final MethodParameter START_PARAMETER = new MethodParameter(
JavaType.INT_PRIMITIVE, "start");
// Fixture
@Mock private JavaType mockIdType;
@Mock private MetadataService mockMetadataService;
@Mock private ServiceAnnotationValuesFactory mockServiceAnnotationValuesFactory;
@Mock private ServiceInterfaceLocator mockServiceInterfaceLocator;
// -- Mocks
@Mock private JavaType mockTargetType;
@Mock private TypeLocationService mockTypeLocationService;
private String pluralId;
// -- Others
private ServiceLayerProvider provider;
/**
* Asserts that asking the {@link ServiceLayerProvider} for a method with
* the given name and parameters results in the given method signature
*
* @param plural
* @param mockServiceInterfaces can be empty
* @param methodId
* @param expectedMethodSignature <code>null</code> means no additions are
* expected
* @param methodParameters
*/
private void assertAdditions(final String plural,
final List<ClassOrInterfaceTypeDetails> mockServiceInterfaces,
final String methodId, final String expectedMethodSignature,
final MethodParameter... methodParameters) {
// Set up
setUpPluralMetadata(plural);
when(mockServiceInterfaceLocator.getServiceInterfaces(mockTargetType))
.thenReturn(mockServiceInterfaces);
// Invoke
final MemberTypeAdditions additions = provider.getMemberTypeAdditions(
CALLER_MID, methodId, mockTargetType, mockIdType,
methodParameters);
// Check
if (expectedMethodSignature == null) {
assertNull("Expected no additions but found: " + additions,
additions);
}
else {
assertNotNull("Expected some additions but was null", additions);
assertEquals(expectedMethodSignature, additions.getMethodCall());
}
}
/**
* Sets up a mock {@link ClassOrInterfaceTypeDetails} for a service
* interface whose {@link RooService} annotation specifies the following
* method names
*
* @param findAllMethod can be blank
* @param saveMethod can be blank
* @param updateMethod can be blank
* @param findEntriesMethod can be blank
* @return a non-<code>null</code> mock
*/
private ClassOrInterfaceTypeDetails getMockService(
final String findAllMethod, final String saveMethod,
final String updateMethod, final String findEntriesMethod) {
final ClassOrInterfaceTypeDetails mockServiceInterface = mock(ClassOrInterfaceTypeDetails.class);
final JavaType mockServiceType = mock(JavaType.class);
final ServiceAnnotationValues mockServiceAnnotationValues = mock(ServiceAnnotationValues.class);
when(mockServiceType.getSimpleTypeName()).thenReturn("PersonService");
when(mockServiceInterface.getName()).thenReturn(mockServiceType);
when(mockServiceInterface.getDeclaredByMetadataId()).thenReturn(
SERVICE_MID);
when(mockServiceAnnotationValues.getFindAllMethod()).thenReturn(
findAllMethod);
when(mockServiceAnnotationValues.getFindEntriesMethod()).thenReturn(
findEntriesMethod);
when(mockServiceAnnotationValues.getSaveMethod())
.thenReturn(saveMethod);
when(mockServiceAnnotationValues.getUpdateMethod()).thenReturn(
updateMethod);
when(
mockServiceAnnotationValuesFactory
.getInstance(mockServiceInterface)).thenReturn(
mockServiceAnnotationValues);
return mockServiceInterface;
}
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
provider = new ServiceLayerProvider();
provider.setMetadataService(mockMetadataService);
provider.setServiceAnnotationValuesFactory(mockServiceAnnotationValuesFactory);
provider.setServiceInterfaceLocator(mockServiceInterfaceLocator);
provider.typeLocationService = mockTypeLocationService;
when(mockTargetType.getFullyQualifiedTypeName()).thenReturn(
"com.example.domain.Person");
when(mockIdType.getFullyQualifiedTypeName()).thenReturn(
Long.class.getName());
when(mockTargetType.getSimpleTypeName()).thenReturn("Person");
when(mockTypeLocationService.getTypePath(mockTargetType)).thenReturn(
Path.SRC_MAIN_JAVA.getModulePathId(""));
pluralId = PluralMetadata.createIdentifier(mockTargetType,
Path.SRC_MAIN_JAVA.getModulePathId(""));
}
/**
* Sets up the mock {@link MetadataService} to return the given plural text
* for our test entity type.
*
* @param plural can be <code>null</code>
*/
private void setUpPluralMetadata(final String plural) {
final PluralMetadata mockPluralMetadata = mock(PluralMetadata.class);
when(mockPluralMetadata.getPlural()).thenReturn(plural);
when(mockMetadataService.get(pluralId)).thenReturn(mockPluralMetadata);
}
@Test
public void testGetAdditionsForBogusMethod() {
final ClassOrInterfaceTypeDetails mockServiceInterface = mock(ClassOrInterfaceTypeDetails.class);
assertAdditions("x", Arrays.asList(mockServiceInterface), BOGUS_METHOD,
null);
}
@Test
public void testGetAdditionsForEntityWithNoServices() {
assertAdditions("x", Arrays.<ClassOrInterfaceTypeDetails> asList(),
BOGUS_METHOD, null);
}
@Test
public void testGetAdditionsForEntityWithNullPluralMetadata() {
// Set up
when(mockMetadataService.get(pluralId)).thenReturn(null);
// Invoke
final MemberTypeAdditions additions = provider.getMemberTypeAdditions(
CALLER_MID, BOGUS_METHOD, mockTargetType, mockIdType);
// Check
assertNull(additions);
}
@Test
public void testGetAdditionsForEntityWithNullPluralText() {
assertAdditions(null, Arrays.<ClassOrInterfaceTypeDetails> asList(),
FIND_ALL.getKey(), null);
}
@Test
public void testGetAdditionsForFindAllMethodWhenServiceDoesNotProvideIt() {
final ClassOrInterfaceTypeDetails mockServiceInterface = getMockService(
"", "x", "x", "x");
assertAdditions("x", Arrays.asList(mockServiceInterface),
FIND_ALL.getKey(), null);
}
@Test
public void testGetAdditionsForFindAllMethodWhenServiceProvidesIt() {
final ClassOrInterfaceTypeDetails mockServiceInterface = getMockService(
"findPerson", "", "x", "x");
assertAdditions("s", Arrays.asList(mockServiceInterface),
FIND_ALL.getKey(), "personService.findPersons()");
}
@Test
public void testGetAdditionsForFindEntriesMethodWhenServiceDoesNotProvideIt() {
final ClassOrInterfaceTypeDetails mockServiceInterface = getMockService(
"x", "x", "x", "");
assertAdditions("x", Arrays.asList(mockServiceInterface),
FIND_ENTRIES.getKey(), null, START_PARAMETER, SIZE_PARAMETER);
}
@Test
public void testGetAdditionsForFindEntriesMethodWhenServiceProvidesIt() {
final ClassOrInterfaceTypeDetails mockServiceInterface = getMockService(
"x", "x", "x", "locate");
assertAdditions("z", Arrays.asList(mockServiceInterface),
FIND_ENTRIES.getKey(),
"personService.locatePersonEntries(start, count)",
START_PARAMETER, SIZE_PARAMETER);
}
@Test
public void testGetAdditionsForSaveMethodWhenServiceDoesNotProvideIt() {
final ClassOrInterfaceTypeDetails mockServiceInterface = getMockService(
"x", null, "x", "x");
final MethodParameter methodParameter = new MethodParameter(
mockTargetType, "anything");
assertAdditions("x", Arrays.asList(mockServiceInterface),
SAVE.getKey(), null, methodParameter);
}
@Test
public void testGetAdditionsForSaveMethodWhenServiceProvidesIt() {
final ClassOrInterfaceTypeDetails mockServiceInterface = getMockService(
"x", "save", "x", "x");
final MethodParameter methodParameter = new MethodParameter(
mockTargetType, "user");
assertAdditions("x", Arrays.asList(mockServiceInterface),
SAVE.getKey(), "personService.savePerson(user)",
methodParameter);
}
@Test
public void testGetAdditionsForUpdateMethodWhenServiceDoesNotProvideIt() {
final ClassOrInterfaceTypeDetails mockServiceInterface = getMockService(
"x", "x", "", "x");
final MethodParameter methodParameter = new MethodParameter(
mockTargetType, "employee");
assertAdditions("x", Arrays.asList(mockServiceInterface),
UPDATE.getKey(), null, methodParameter);
}
@Test
public void testGetAdditionsForUpdateMethodWhenServiceProvidesIt() {
final ClassOrInterfaceTypeDetails mockServiceInterface = getMockService(
"x", "x", "change", "x");
final MethodParameter methodParameter = new MethodParameter(
mockTargetType, "bob");
assertAdditions("x", Arrays.asList(mockServiceInterface),
UPDATE.getKey(), "personService.changePerson(bob)",
methodParameter);
}
@Test
public void testGetAdditionsWhenServiceAnnotationValuesUnavailable() {
final ClassOrInterfaceTypeDetails mockServiceInterface = mock(ClassOrInterfaceTypeDetails.class);
assertAdditions("anything", Arrays.asList(mockServiceInterface),
BOGUS_METHOD, null);
}
}