Skip to content

Commit

Permalink
Add basic integration tests for all BaseController extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
dnlkoch committed Oct 16, 2021
1 parent 233c6c9 commit cda6dc3
Show file tree
Hide file tree
Showing 6 changed files with 563 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/* SHOGun, https://terrestris.github.io/shogun/
*
* Copyright © 2020-present terrestris GmbH & Co. KG
*
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0.txt
*
* 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 de.terrestris.shogun.boot.controller;

import de.terrestris.shogun.lib.controller.ApplicationController;
import de.terrestris.shogun.lib.model.Application;
import de.terrestris.shogun.lib.repository.ApplicationRepository;

import java.util.ArrayList;
import java.util.List;

public class ApplicationControllerTest extends BaseControllerTest<ApplicationController, ApplicationRepository, Application> {

public void setBasePath() {
basePath = "/applications";
}

public void insertTestData() {
Application entity1 = new Application();
Application entity2 = new Application();
Application entity3 = new Application();

entity1.setName("Application 1");
entity2.setName("Application 2");
entity3.setName("Application 3");

ArrayList<Application> entities = new ArrayList<>();

entities.add(entity1);
entities.add(entity2);
entities.add(entity3);

List<Application> persistedEntities = (List<Application>) repository.saveAll(entities);

testData = persistedEntities;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
/* SHOGun, https://terrestris.github.io/shogun/
*
* Copyright © 2020-present terrestris GmbH & Co. KG
*
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0.txt
*
* 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 de.terrestris.shogun.boot.controller;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import de.terrestris.shogun.boot.config.ApplicationConfig;
import de.terrestris.shogun.boot.config.JdbcConfiguration;
import de.terrestris.shogun.lib.controller.BaseController;
import de.terrestris.shogun.lib.model.BaseEntity;
import de.terrestris.shogun.lib.model.User;
import de.terrestris.shogun.lib.repository.BaseCrudRepository;
import de.terrestris.shogun.lib.repository.UserRepository;
import de.terrestris.shogun.lib.repository.security.permission.UserClassPermissionRepository;
import de.terrestris.shogun.lib.repository.security.permission.UserInstancePermissionRepository;
import de.terrestris.shogun.lib.security.SecurityContextUtil;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.keycloak.representations.idm.UserRepresentation;
import org.mockito.ArgumentMatchers;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.servlet.server.Encoding;
import org.springframework.http.MediaType;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;

@SpringBootTest(
classes = {
ApplicationConfig.class,
JdbcConfiguration.class
},
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
)
@ActiveProfiles("test")
public abstract class BaseControllerTest<U extends BaseController, R extends BaseCrudRepository, S extends BaseEntity> implements IBaseController {

@Autowired
protected R repository;

@Autowired
protected UserRepository userRepository;

@Autowired
protected UserInstancePermissionRepository userInstancePermissionRepository;

@Autowired
protected UserClassPermissionRepository userClassPermissionRepository;

@Autowired
private WebApplicationContext context;

@Autowired
protected ObjectMapper objectMapper;

protected String basePath;

protected MockMvc mockMvc;

protected List<S> testData;

protected User adminUser;

public void initMockMvc() {
this.mockMvc = MockMvcBuilders
.webAppContextSetup(context)
.alwaysDo(print())
.apply(springSecurity())
.build();
}

public void initAdminUser() {
User adminUser = new User();
String keycloakId = "bf5efad6-50f5-448c-b808-60dc0259d70b";
adminUser.setKeycloakId(keycloakId);
UserRepresentation keycloakRepresentation = new UserRepresentation();
keycloakRepresentation.setEmail("[email protected]");
keycloakRepresentation.setEnabled(true);
keycloakRepresentation.setUsername("admin");
ArrayList<String> realmRoles = new ArrayList<>();
realmRoles.add("ROLE_ADMIN");
keycloakRepresentation.setRealmRoles(realmRoles);
adminUser.setKeycloakRepresentation(keycloakRepresentation);

User persistedAdminUser = userRepository.save(adminUser);

this.adminUser = persistedAdminUser;
}

public void deinitAdminUser() {
userInstancePermissionRepository.deleteAll();
userClassPermissionRepository.deleteAll();

userRepository.delete(this.adminUser);
}

public void cleanupTestData() {
repository.deleteAll();
}

@BeforeEach
public void setUp() {
initMockMvc();
initAdminUser();
setBasePath();
insertTestData();
}

@AfterEach
public void teardown() {
deinitAdminUser();
cleanupTestData();
}

@Test
public void findAll_shouldReturnAllAvailableEntitiesForRoleAdmin() throws Exception {
this.mockMvc
.perform(
MockMvcRequestBuilders
.get(basePath)
.with(user("admin").password("pass").roles("ADMIN"))
)
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$").isArray())
.andExpect(jsonPath("$", hasSize(testData.size())));
}

@Test
public void findOne_shouldReturnAnAvailableEntityForRoleAdmin() throws Exception {
this.mockMvc
.perform(
MockMvcRequestBuilders
.get(String.format("%s/%s", basePath, testData.get(0).getId()))
.with(user("admin").password("pass").roles("ADMIN"))
)
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$").exists())
.andExpect(jsonPath("$", hasEntry("id", testData.get(0).getId().intValue())));
}

@Test
public void add_shouldCreateTheEntityForRoleAdmin() throws Exception {
try (MockedStatic<SecurityContextUtil> utilities = Mockito.mockStatic(SecurityContextUtil.class)) {
utilities.when(() -> SecurityContextUtil.getKeycloakUserIdFromAuthentication(ArgumentMatchers.any()))
.thenReturn(this.adminUser.getKeycloakId());

JsonNode insertNode = objectMapper.valueToTree(testData.get(0));
List<String> fieldsToRemove = List.of("id", "created", "modified");
insertNode = ((ObjectNode) insertNode).remove(fieldsToRemove);

this.mockMvc
.perform(
MockMvcRequestBuilders
.post(String.format("%s", basePath))
.contentType(MediaType.APPLICATION_JSON)
.characterEncoding(Encoding.DEFAULT_CHARSET.toString())
.content(objectMapper.writeValueAsString(insertNode))
.with(user("admin").password("pass").roles("ADMIN"))
.with(csrf())
)
.andExpect(MockMvcResultMatchers.status().isCreated())
.andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$").exists())
.andExpect(jsonPath("$", hasKey("id")));
}

List<S> persistedEntities = repository.findAll();
assertEquals(4, persistedEntities.size());
}

@Test
public void update_shouldUpdateTheEntityForRoleAdmin() throws Exception {
JsonNode updateNode = objectMapper.valueToTree(testData.get(0));
List<String> fieldsToRemove = List.of("created", "modified");
updateNode = ((ObjectNode) updateNode).remove(fieldsToRemove);

this.mockMvc
.perform(
MockMvcRequestBuilders
.put(String.format("%s/%s", basePath, testData.get(0).getId()))
.contentType(MediaType.APPLICATION_JSON)
.characterEncoding(Encoding.DEFAULT_CHARSET.toString())
.content(objectMapper.writeValueAsString(updateNode))
.with(user("admin").password("pass").roles("ADMIN"))
.with(csrf())
)
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$").exists())
.andExpect(jsonPath("$", hasKey("id")));

Optional<S> updatedEntity = repository.findById(testData.get(0).getId());
assertNotEquals(updatedEntity.get().getCreated(), updatedEntity.get().getModified());
}

@Test
public void delete_shouldDeleteAnAvailableEntityForRoleAdmin() throws Exception {
this.mockMvc
.perform(
MockMvcRequestBuilders
.delete(String.format("%s/%s", basePath, testData.get(0).getId()))
.with(user("admin").password("pass").roles("ADMIN"))
.with(csrf())
)
.andExpect(MockMvcResultMatchers.status().isNoContent());

List<S> persistedEntities = repository.findAll();
assertEquals(2, persistedEntities.size());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/* SHOGun, https://terrestris.github.io/shogun/
*
* Copyright © 2020-present terrestris GmbH & Co. KG
*
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0.txt
*
* 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 de.terrestris.shogun.boot.controller;

import de.terrestris.shogun.lib.controller.GroupController;
import de.terrestris.shogun.lib.model.Group;
import de.terrestris.shogun.lib.repository.GroupRepository;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class GroupControllerTest extends BaseControllerTest<GroupController, GroupRepository, Group> {

public void setBasePath() {
basePath = "/groups";
}

public void insertTestData() {
Group entity1 = new Group();
Group entity2 = new Group();
Group entity3 = new Group();

entity1.setKeycloakId(UUID.randomUUID().toString());
entity2.setKeycloakId(UUID.randomUUID().toString());
entity3.setKeycloakId(UUID.randomUUID().toString());

ArrayList<Group> entities = new ArrayList<>();

entities.add(entity1);
entities.add(entity2);
entities.add(entity3);

List<Group> persistedEntities = (List<Group>) repository.saveAll(entities);

testData = persistedEntities;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/* SHOGun, https://terrestris.github.io/shogun/
*
* Copyright © 2020-present terrestris GmbH & Co. KG
*
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0.txt
*
* 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 de.terrestris.shogun.boot.controller;

public interface IBaseController {
void setBasePath();
void insertTestData();
}
Loading

0 comments on commit cda6dc3

Please sign in to comment.