/*
* Copyright (c) 2009 Lockheed Martin Corporation
*
* 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.
*/
package org.eurekastreams.server.service.restlets;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.persistence.NoResultException;
import net.sf.json.JSONObject;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.lib.legacy.ClassImposteriser;
import org.junit.Test;
import org.restlet.Context;
import org.restlet.data.MediaType;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.resource.Representation;
import org.restlet.resource.ResourceException;
import org.restlet.resource.Variant;
import org.eurekastreams.server.domain.BackgroundItem;
import org.eurekastreams.server.domain.BackgroundItemType;
import org.eurekastreams.server.domain.Enrollment;
import org.eurekastreams.server.persistence.EnrollmentMapper;
/**
* Test class for EnrollmentEntryResource.
*/
public class EnrollmentEntryResourceTest
{
/**
* Subject under test.
*/
private EnrollmentsEntryResource sut;
/**
* Context for building mock objects.
*/
private final Mockery context = new JUnit4Mockery()
{
{
setImposteriser(ClassImposteriser.INSTANCE);
}
};
/**
* Mocked restlet context.
*/
private Context restContext = context.mock(Context.class);
/**
* Mocked request.
*/
private Request request = context.mock(Request.class);
/**
* Mocked response.
*/
private Response response = context.mock(Response.class);
/**
* Adapter mock for the Response object.
*/
private ResponseAdapter responseAdapter = context.mock(ResponseAdapter.class);
/**
* Mocked enrollment mapper.
*/
private EnrollmentMapper enrollmentMapper = context.mock(EnrollmentMapper.class);
/**
* Mock enrollment.
*/
private final Enrollment enrollment = context.mock(Enrollment.class);
/**
* UUID to represent a Person. Arbitrary.
*/
private String uuid = UUID.randomUUID().toString();
/**
* the school name used for test.
*/
private final String schoolName = "school name";
/**
* A enrollment id for testing. Arbitrary.
*/
private static final String ENROLLMENT_ID = "235";
/**
* Set up the SUT.
*
* @param inUuid
* uuid to load into attributes.
* @param inEnrollmentId
* enrollmentId to load into attributes.
* @throws ParseException
* should not occur.
*/
private void setupSutAttributesExpectations(final String inUuid, final String inEnrollmentId) throws ParseException
{
final Map<String, Object> attributes = new HashMap<String, Object>();
attributes.put("uuid", inUuid);
attributes.put("enrollmentId", inEnrollmentId);
context.checking(new Expectations()
{
{
allowing(request).getAttributes();
will(returnValue(attributes));
}
});
sut = new EnrollmentsEntryResource();
sut.init(restContext, request, response);
sut.setEnrollmentMapper(enrollmentMapper);
sut.setAdaptedResponse(responseAdapter);
}
/**
* Test the GET call.
*
* @throws ResourceException
* not expected.
* @throws IOException
* not expected.
* @throws ParseException
* not expected.
*/
@Test
public void represent() throws ResourceException, IOException, ParseException
{
final Variant variant = context.mock(Variant.class);
setupSutAttributesExpectations(uuid, ENROLLMENT_ID);
setEnrollmentExpecations();
context.checking(new Expectations()
{
{
oneOf(enrollmentMapper).findById(Long.valueOf(ENROLLMENT_ID));
will(returnValue(enrollment));
}
});
Representation actual = sut.represent(variant);
assertEquals("MediaType doesn't match", MediaType.APPLICATION_JSON, actual.getMediaType());
JSONObject json = JSONObject.fromObject(actual.getText());
String actualSchoolName = (String) json.get(EnrollmentsCollectionResource.SCHOOL_NAME_KEY);
assertTrue("Incorrect school name", actualSchoolName.equals(schoolName));
assertEquals("Incorrect number of activities", 3, json.getJSONArray(
EnrollmentsCollectionResource.ACTIVITIES_KEY).size());
assertEquals("Incorrect number of areas of study", 4, json.getJSONArray(
EnrollmentsCollectionResource.AREAS_OF_STUDY_KEY).size());
context.assertIsSatisfied();
}
/**
* Test represent method with bad id. Expected exception.
*
* @throws ResourceException
* Expected.
* @throws ParseException
* Not expected.
*/
@Test(expected = ResourceException.class)
public void testRepresentBadId() throws ResourceException, ParseException
{
setupSutAttributesExpectations(uuid, ENROLLMENT_ID);
final Variant variant = context.mock(Variant.class);
context.checking(new Expectations()
{
{
oneOf(enrollmentMapper).findById(Long.valueOf(ENROLLMENT_ID));
will(throwException(new NoResultException()));
}
});
sut.represent(variant);
}
/**
* Test the PUT functionality.
*
* @throws ResourceException
* not expected
* @throws IOException
* not expected
* @throws ParseException
* not expected.
*/
@Test
public void storeRepresentation() throws ResourceException, IOException, ParseException
{
setupSutAttributesExpectations(uuid, ENROLLMENT_ID);
setEnrollmentExpecations();
Representation entity = setupPUTExpectations(false);
context.checking(new Expectations()
{
{
oneOf(enrollmentMapper).flush(uuid);
}
});
sut.storeRepresentation(entity);
context.assertIsSatisfied();
}
/**
* Test method when entity.getText throws IOException.
*
* @throws ResourceException
* expected.
* @throws IOException
* not expected.
* @throws ParseException
* not expected.
*/
@Test(expected = ResourceException.class)
public void storeRepresentationIOException() throws ResourceException, IOException, ParseException
{
setupSutAttributesExpectations(uuid, ENROLLMENT_ID);
setEnrollmentExpecations();
Representation entity = setupPUTExpectations(true);
sut.storeRepresentation(entity);
context.assertIsSatisfied();
}
/**
* Test the PUT functionality when the client does not provide a closing date.
*
* @throws ResourceException
* not expected
* @throws IOException
* not expected
* @throws ParseException
* not expected.
*/
@Test
public void storeRepresentationForPresentEnrollment() throws ResourceException, IOException, ParseException
{
setupSutAttributesExpectations(uuid, ENROLLMENT_ID);
setEnrollmentExpecations();
Representation entity = setupPUTExpectations(false);
context.checking(new Expectations()
{
{
oneOf(enrollmentMapper).flush(uuid);
}
});
sut.storeRepresentation(entity);
context.assertIsSatisfied();
}
/**
* Test the PUT functionality when the provided enrollment id does not correspond to a enrollment in the db. Should
* throw a ResourceException with a 404.
*
* @throws ResourceException
* not expected
* @throws IOException
* not expected
* @throws ParseException
* not expected
*/
@Test(expected = ResourceException.class)
public void storeRepresentationWithBadId() throws ResourceException, IOException, ParseException
{
setupSutAttributesExpectations(uuid, ENROLLMENT_ID);
final Representation entity = context.mock(Representation.class);
context.checking(new Expectations()
{
{
oneOf(enrollmentMapper).findById(Long.valueOf(ENROLLMENT_ID));
will(returnValue(null));
}
});
sut.storeRepresentation(entity);
context.assertIsSatisfied();
}
/**
* Thest the PUT function and excercise validation with a bad enrollment JSON string. Should throw a Resource
* Exception.
*
* @throws ResourceException
* - Expected with a validation error.
* @throws IOException
* - non expected.
* @throws ParseException
* - not expected.
*/
@Test(expected = ResourceException.class)
public void testValidationResourceException() throws ResourceException, IOException, ParseException
{
setupSutAttributesExpectations(uuid, ENROLLMENT_ID);
setEnrollmentExpecations();
final Representation entity = context.mock(Representation.class);
final String jsonString = "{\"areasofstudy\":[],\"id\":\"235\",\"graddate\":\"baddate\",\"degree\""
+ ":\"Bachelors\",\"schoolname\":\"\",\"activities\":[\"stuff\"],\"additionaldetails\":\"some stuff\"}";
context.checking(new Expectations()
{
{
oneOf(enrollmentMapper).findById(Long.valueOf(ENROLLMENT_ID));
will(returnValue(enrollment));
oneOf(entity).getText();
will(returnValue(jsonString));
}
});
sut.storeRepresentation(entity);
context.assertIsSatisfied();
}
/**
* Test the DELETE functionality.
*
* @throws ParseException
* on error.
*
*/
@Test
public void removeRepresentations() throws ParseException
{
setupSutAttributesExpectations(uuid, ENROLLMENT_ID);
context.checking(new Expectations()
{
{
oneOf(enrollmentMapper).delete(Long.valueOf(ENROLLMENT_ID));
oneOf(enrollmentMapper).flush(uuid);
}
});
sut.removeRepresentations();
context.assertIsSatisfied();
}
/**
* Helper method to set up enrollment mock so it can respond to calls.
*
* @throws ParseException
* not expected.
*/
private void setEnrollmentExpecations() throws ParseException
{
final long enrollmentId = 2L;
final String degree = "BS Computer Sciences";
DateFormat df = new SimpleDateFormat("yyyy");
final Date gradDate = df.parse("2008");
final String additionalDetails = "this that and the other thing";
final List<BackgroundItem> areasOfStudy = new ArrayList<BackgroundItem>();
areasOfStudy.add(new BackgroundItem("electrical engineering", BackgroundItemType.AREA_OF_STUDY));
areasOfStudy.add(new BackgroundItem("computer scientce", BackgroundItemType.AREA_OF_STUDY));
areasOfStudy.add(new BackgroundItem("music", BackgroundItemType.AREA_OF_STUDY));
areasOfStudy.add(new BackgroundItem("goofing off", BackgroundItemType.AREA_OF_STUDY));
final List<BackgroundItem> activities = new ArrayList<BackgroundItem>();
activities.add(new BackgroundItem("marching band", BackgroundItemType.ACTIVITY_OR_SOCIETY));
activities.add(new BackgroundItem("computer geek club", BackgroundItemType.ACTIVITY_OR_SOCIETY));
activities.add(new BackgroundItem("ieee", BackgroundItemType.ACTIVITY_OR_SOCIETY));
context.checking(new Expectations()
{
{
// create JSON representation
allowing(enrollment).getId();
will(returnValue(enrollmentId));
oneOf(enrollment).getSchoolName();
will(returnValue(schoolName));
oneOf(enrollment).getDegree();
will(returnValue(degree));
oneOf(enrollment).getAreasOfStudy();
will(returnValue(areasOfStudy));
oneOf(enrollment).getGradDate();
will(returnValue(gradDate));
oneOf(enrollment).getActivities();
will(returnValue(activities));
oneOf(enrollment).getAdditionalDetails();
will(returnValue(additionalDetails));
}
});
}
/**
* Set up the expectations common to the two PUT tests.
*
* @param throwIOException
* If entity.getText should throw IOException or not.
* @return a representation to pass to the storeRepresentation method
* @throws IOException
* not expected
* @throws ParseException
* not expected.
*/
@SuppressWarnings("unchecked")
private Representation setupPUTExpectations(final boolean throwIOException) throws IOException, ParseException
{
this.setEnrollmentExpecations();
final Representation entity = context.mock(Representation.class);
final String jsonString = sut.convertEnrollmentToJSONObject(enrollment).toString();
DateFormat df = new SimpleDateFormat("yyyy");
final Date gradDate = df.parse("2008");
context.checking(new Expectations()
{
{
oneOf(enrollmentMapper).findById(Long.valueOf(ENROLLMENT_ID));
will(returnValue(enrollment));
if (throwIOException)
{
oneOf(entity).getText();
will(throwException(new IOException()));
}
else
{
oneOf(entity).getText();
will(returnValue(jsonString));
}
oneOf(enrollment).setActivities(with(any(List.class)));
oneOf(enrollment).setAreasOfStudy(with(any(List.class)));
oneOf(enrollment).setSchoolName(with(any(String.class)));
oneOf(enrollment).setDegree(with(any(String.class)));
oneOf(enrollment).setGradDate(with(gradDate));
oneOf(enrollment).setAdditionalDetails(with(any(String.class)));
oneOf(responseAdapter).setEntity(with(any(String.class)), with(any(MediaType.class)));
}
});
return entity;
}
}