package de.terrestris.shogun2.rest;

import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import java.util.Arrays;

import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import de.terrestris.shogun2.model.PersistentObject;
import de.terrestris.shogun2.service.AbstractCrudService;

/**
 *
 * @author Kai Volland
 * @author Nils Bühner
 *
 */
public class AbstractRestControllerTest {

	/**
	 * A private model class for that exists only to test the
	 * {@link AbstractRestController}.
	 *
	 */
	private class TestModel extends PersistentObject {
		private static final long serialVersionUID = 1L;
		private String testValue;
		@SuppressWarnings("unused")
		public String getTestValue() {return testValue;}
		public void setTestValue(String testValue) {this.testValue = testValue;}
	}

	/**
	 * A private REST controller for the {@link TestModel}. This class
	 * only exists in the scope of this test and is used to test the
	 * {@link AbstractRestController}.
	 */
	@RestController
	@RequestMapping("/test")
	private class TestModelRestController extends AbstractRestController<TestModel> {}

	/**
	 * Spring MVC test support
	 */
	private MockMvc mockMvc;

	/**
	 * The service, whose behavior will be mocked up. It will be injected to the
	 * controller to test.
	 */
	@Mock
	private AbstractCrudService<TestModel> serviceMock;

	/**
	 * The controller that will be tested.
	 */
	@InjectMocks
	private AbstractRestController<TestModel> restController;

	/**
	 * Test setup and init of mocks.
	 */
	@Before
	public void setUp() {

		restController = new TestModelRestController();

		// Process mock annotations
		MockitoAnnotations.initMocks(this);

		// Setup Spring test in standalone mode
		this.mockMvc = MockMvcBuilders.standaloneSetup(restController).build();
	}

	/**
	 * Tests whether the REST findAll interface will return all entities and a
	 * HTTP Status Code 200 (OK).
	 * 
	 * @throws Exception
	 */
	@Test
	public void findAllEntities_shouldReturn_ListOfEntitiesAndOK()
			throws Exception {
		String firstValue = "value 1";
		String secondValue = "value 2";

		TestModel first = new TestModel();
		first.setTestValue(firstValue);

		TestModel second = new TestModel();
		second.setTestValue(secondValue);

		when(serviceMock.findAll()).thenReturn(Arrays.asList(first, second));

		// Test GET method
		mockMvc.perform(get("/test"))
			.andExpect(status().isOk())
			.andExpect(content().contentType("application/json;charset=UTF-8"))
			.andExpect(jsonPath("$", hasSize(2)))
			.andExpect(jsonPath("$[0].testValue", is(firstValue)))
			.andExpect(jsonPath("$[1].testValue", is(secondValue)));

		verify(serviceMock, times(1)).findAll();
		verifyNoMoreInteractions(serviceMock);
	}
}

@@ -1180,16 +1180,65 @@
 Service;
+%0Aimport de.terrestris.shogun2.util.test.TestUtil;
 %0A%0A/**%0A *
@@ -1954,16 +1954,17 @@
 g(%22/test
+s
 %22)%0A%09priv
@@ -2837,17 +2837,16 @@
 OK).%0A%09 *
- 
 %0A%09 * @th
@@ -3295,16 +3295,17 @@
 t(%22/test
+s
 %22))%0A%09%09%09.
@@ -3646,13 +3646,830 @@
 eMock);%0A
-
 %09%7D%0A
+%0A%09/**%0A%09 * Tests whether the REST findById interface will return an expected entity%0A%09 * and a HTTP Status Code 200 (OK).%0A%09 * @throws Exception%0A%09 *%0A%09 */%0A%09@Test%0A%09public void findById_shouldReturn_EntityAndOK() throws Exception %7B%0A%09%09int id = 42;%0A%09%09String value = %22value%22;%0A%0A%09%09TestModel testInstance = new TestModel();%0A%09%09testInstance.setTestValue(value);%0A%0A%09%09TestUtil.setIdOnPersistentObject(testInstance, id);%0A%0A%09%09when(serviceMock.findById(id)).thenReturn(testInstance);%0A%0A%09%09// Test GET method with ID%0A%09%09mockMvc.perform(get(%22/tests/%22 + id))%0A%09%09%09.andExpect(status().isOk())%0A%09%09%09.andExpect(content().contentType(%22application/json;charset=UTF-8%22))%0A%09%09%09.andExpect(jsonPath(%22$.id%22, is(id)))%0A%09%09%09.andExpect(jsonPath(%22$.testValue%22, is(value)));%0A%0A%09%09verify(serviceMock, times(1)).findById(id);%0A%09%09verifyNoMoreInteractions(serviceMock);%0A%09%7D%0A%0A
 %7D%0A

Add test for REST/findById