improve test code coverage and introduce context.register
This commit is contained in:
build.gradle
src
main
java
net
hostsharing
hsadminng
test
java
net
hostsharing
hsadminng
context
hs
rbac
test
@@ -17,6 +17,15 @@ class ContextIntegrationTests {
|
||||
@Autowired
|
||||
private Context context;
|
||||
|
||||
@Test
|
||||
void registerWithoutHttpServletRequestUsesCallStack() {
|
||||
|
||||
context.register("current-user", null);
|
||||
|
||||
final var currentTask = context.getCurrentTask();
|
||||
assertThat(currentTask).isEqualTo("ContextIntegrationTests.registerWithoutHttpServletRequestUsesCallStack");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void setCurrentUser() {
|
||||
|
@@ -0,0 +1,37 @@
|
||||
package net.hostsharing.hsadminng.context;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.Query;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class ContextUnitTest {
|
||||
|
||||
@Mock
|
||||
EntityManager em;
|
||||
|
||||
@Mock
|
||||
Query nativeQuery;
|
||||
|
||||
@InjectMocks
|
||||
Context context;
|
||||
|
||||
@Test
|
||||
void registerWithoutHttpServletRequestUsesCallStack() {
|
||||
given(em.createNativeQuery(any())).willReturn(nativeQuery);
|
||||
|
||||
context.register("current-user", null);
|
||||
|
||||
verify(em).createNativeQuery(
|
||||
"set local hsadminng.currentTask = 'ContextUnitTest.registerWithoutHttpServletRequestUsesCallStack';");
|
||||
}
|
||||
}
|
@@ -118,9 +118,9 @@ class CustomerControllerAcceptanceTest {
|
||||
.contentType(ContentType.JSON)
|
||||
.body("""
|
||||
{
|
||||
"reference": 90010,
|
||||
"prefix": "vvv",
|
||||
"adminUserName": "customer-admin@vvv.example.com"
|
||||
"reference": 90020,
|
||||
"prefix": "ttt",
|
||||
"adminUserName": "customer-admin@ttt.example.com"
|
||||
}
|
||||
""")
|
||||
.port(port)
|
||||
@@ -129,16 +129,54 @@ class CustomerControllerAcceptanceTest {
|
||||
.then().assertThat()
|
||||
.statusCode(201)
|
||||
.contentType(ContentType.JSON)
|
||||
.body("prefix", is("vvv"))
|
||||
.body("prefix", is("ttt"))
|
||||
.header("Location", startsWith("http://localhost"))
|
||||
.extract().header("Location"); // @formatter:on
|
||||
|
||||
// finally, the new customer can be viewed by its own admin
|
||||
final var newUserUuid = UUID.fromString(
|
||||
location.substring(location.lastIndexOf('/') + 1));
|
||||
context.setCurrentUser("customer-admin@ttt.example.com");
|
||||
assertThat(customerRepository.findByUuid(newUserUuid))
|
||||
.hasValueSatisfying(c -> assertThat(c.getPrefix()).isEqualTo("ttt"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void hostsharingAdmin_withoutAssumedRole_canCreateCustomerWithGivenUuid() {
|
||||
|
||||
final var givenUuid = UUID.randomUUID();
|
||||
|
||||
final var location = RestAssured // @formatter:off
|
||||
.given()
|
||||
.header("current-user", "mike@hostsharing.net")
|
||||
.contentType(ContentType.JSON)
|
||||
.body("""
|
||||
{
|
||||
"uuid": "%s",
|
||||
"reference": 90010,
|
||||
"prefix": "vvv",
|
||||
"adminUserName": "customer-admin@vvv.example.com"
|
||||
}
|
||||
""".formatted(givenUuid))
|
||||
.port(port)
|
||||
.when()
|
||||
.post("http://localhost/api/customers")
|
||||
.then().assertThat()
|
||||
.statusCode(201)
|
||||
.contentType(ContentType.JSON)
|
||||
.body("prefix", is("vvv"))
|
||||
.header("Location", startsWith("http://localhost"))
|
||||
.extract().header("Location"); // @formatter:on
|
||||
|
||||
// finally, the new customer can be viewed by its own admin
|
||||
final var newUserUuid = UUID.fromString(
|
||||
location.substring(location.lastIndexOf('/') + 1));
|
||||
context.setCurrentUser("customer-admin@vvv.example.com");
|
||||
assertThat(customerRepository.findByUuid(newUserUuid))
|
||||
.hasValueSatisfying(c -> assertThat(c.getPrefix()).isEqualTo("vvv"));
|
||||
.hasValueSatisfying(c -> {
|
||||
assertThat(c.getPrefix()).isEqualTo("vvv");
|
||||
assertThat(c.getUuid()).isEqualTo(givenUuid);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@@ -1,152 +0,0 @@
|
||||
package net.hostsharing.hsadminng.hs.hspackage;
|
||||
|
||||
import net.hostsharing.hsadminng.config.JsonObjectMapperConfiguration;
|
||||
import net.hostsharing.hsadminng.context.Context;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@WebMvcTest(PackageController.class)
|
||||
@ContextConfiguration(classes = { PackageController.class, JsonObjectMapperConfiguration.class })
|
||||
class PackageControllerRestTest {
|
||||
|
||||
@Autowired
|
||||
MockMvc mockMvc;
|
||||
@MockBean
|
||||
Context contextMock;
|
||||
@MockBean
|
||||
PackageRepository packageRepositoryMock;
|
||||
|
||||
@Nested
|
||||
class ListPackages {
|
||||
|
||||
@Test
|
||||
void withoutNameParameter() throws Exception {
|
||||
|
||||
// given
|
||||
final var givenPacs = List.of(TestPackage.xxx00, TestPackage.xxx01, TestPackage.xxx02);
|
||||
when(packageRepositoryMock.findAllByOptionalNameLike(null)).thenReturn(givenPacs);
|
||||
|
||||
// when
|
||||
mockMvc.perform(MockMvcRequestBuilders
|
||||
.get("/api/packages")
|
||||
.header("current-user", "mike@hostsharing.net")
|
||||
.header("assumed-roles", "customer#xxx.admin")
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
|
||||
// then
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", hasSize(3)))
|
||||
.andExpect(jsonPath("$[0].name", is("xxx00")))
|
||||
.andExpect(jsonPath("$[1].uuid", is(TestPackage.xxx01.getUuid().toString())))
|
||||
.andExpect(jsonPath("$[2].customer.prefix", is("xxx")));
|
||||
|
||||
verify(contextMock).setCurrentUser("mike@hostsharing.net");
|
||||
verify(contextMock).assumeRoles("customer#xxx.admin");
|
||||
}
|
||||
|
||||
@Test
|
||||
void withNameParameter() throws Exception {
|
||||
|
||||
// given
|
||||
final var givenPacs = List.of(TestPackage.xxx01);
|
||||
when(packageRepositoryMock.findAllByOptionalNameLike("xxx01")).thenReturn(givenPacs);
|
||||
|
||||
// when
|
||||
mockMvc.perform(MockMvcRequestBuilders
|
||||
.get("/api/packages?name=xxx01")
|
||||
.header("current-user", "mike@hostsharing.net")
|
||||
.header("assumed-roles", "customer#xxx.admin")
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
|
||||
// then
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", hasSize(1)))
|
||||
.andExpect(jsonPath("$[0].name", is("xxx01")));
|
||||
|
||||
verify(contextMock).setCurrentUser("mike@hostsharing.net");
|
||||
verify(contextMock).assumeRoles("customer#xxx.admin");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
class updatePackage {
|
||||
|
||||
@Test
|
||||
void withDescriptionUpdatesDescription() throws Exception {
|
||||
|
||||
// given
|
||||
final var givenPac = TestPackage.xxx01;
|
||||
when(packageRepositoryMock.findByUuid(givenPac.getUuid())).thenReturn(givenPac);
|
||||
when(packageRepositoryMock.save(any())).thenAnswer(invocation -> invocation.getArgument(0));
|
||||
|
||||
// when
|
||||
mockMvc.perform(MockMvcRequestBuilders
|
||||
.patch("/api/packages/" + givenPac.getUuid().toString())
|
||||
.header("current-user", "mike@hostsharing.net")
|
||||
.header("assumed-roles", "customer#xxx.admin")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("""
|
||||
{
|
||||
"description": "some description"
|
||||
}
|
||||
""")
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
|
||||
// then
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("description", is("some description")));
|
||||
|
||||
verify(contextMock).setCurrentUser("mike@hostsharing.net");
|
||||
verify(contextMock).assumeRoles("customer#xxx.admin");
|
||||
verify(packageRepositoryMock).save(argThat(entity ->
|
||||
entity.getDescription().equals("some description") &&
|
||||
entity.getUuid().equals(givenPac.getUuid())));
|
||||
}
|
||||
|
||||
@Test
|
||||
void withoutDescriptionDoesNothing() throws Exception {
|
||||
|
||||
// given
|
||||
final var givenPac = TestPackage.xxx01;
|
||||
when(packageRepositoryMock.findByUuid(givenPac.getUuid())).thenReturn(givenPac);
|
||||
when(packageRepositoryMock.save(any())).thenAnswer(invocation -> invocation.getArgument(0));
|
||||
|
||||
// when
|
||||
mockMvc.perform(MockMvcRequestBuilders
|
||||
.patch("/api/packages/" + givenPac.getUuid().toString())
|
||||
.header("current-user", "mike@hostsharing.net")
|
||||
.header("assumed-roles", "customer#xxx.admin")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("{}")
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
|
||||
// then
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("description", is(givenPac.getDescription())));
|
||||
|
||||
verify(contextMock).setCurrentUser("mike@hostsharing.net");
|
||||
verify(contextMock).assumeRoles("customer#xxx.admin");
|
||||
verify(packageRepositoryMock).save(argThat(entity ->
|
||||
givenPac.getDescription().equals(entity.getDescription()) &&
|
||||
givenPac.getUuid().equals(entity.getUuid())));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
package net.hostsharing.hsadminng.rbac.rbacgrant;
|
||||
|
||||
import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleType;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class RbacGrantEntityUnitTest {
|
||||
|
||||
@Test
|
||||
void getRbacGrantId() {
|
||||
// given
|
||||
final var grantedRoleUuid = UUID.randomUUID();
|
||||
final var granteeUserUuid = UUID.randomUUID();
|
||||
final var entity = new RbacGrantEntity();
|
||||
entity.setGrantedRoleUuid(grantedRoleUuid);
|
||||
entity.setGranteeUserUuid(granteeUserUuid);
|
||||
|
||||
// when
|
||||
final var grantId = entity.getRbacGrantId();
|
||||
|
||||
// then
|
||||
assertThat(grantId).isEqualTo(new RbacGrantId(granteeUserUuid, grantedRoleUuid));
|
||||
}
|
||||
|
||||
@Test
|
||||
void toDisplayAssumed() {
|
||||
// given
|
||||
final var entity = new RbacGrantEntity( // @formatter:off
|
||||
"GrantER", UUID.randomUUID(),
|
||||
"GrantED", UUID.randomUUID(),
|
||||
"GrantEE", UUID.randomUUID(),
|
||||
true,
|
||||
"ObjectTable", "ObjectId", UUID.randomUUID(),
|
||||
RbacRoleType.admin); // @formatter:on
|
||||
|
||||
// when
|
||||
final var display = entity.toDisplay();
|
||||
|
||||
// then
|
||||
assertThat(display).isEqualTo("{ grant assumed role GrantED to user GrantEE by role GrantER }");
|
||||
}
|
||||
|
||||
@Test
|
||||
void toDisplayNotAssumed() {
|
||||
// given
|
||||
final var entity = new RbacGrantEntity( // @formatter:off
|
||||
"GrantER", UUID.randomUUID(),
|
||||
"GrantED", UUID.randomUUID(),
|
||||
"GrantEE", UUID.randomUUID(),
|
||||
false,
|
||||
"ObjectTable", "ObjectId", UUID.randomUUID(),
|
||||
RbacRoleType.owner); // @formatter:on
|
||||
|
||||
// when
|
||||
final var display = entity.toDisplay();
|
||||
|
||||
// then
|
||||
assertThat(display).isEqualTo("{ grant role GrantED to user GrantEE by role GrantER }");
|
||||
}
|
||||
}
|
71
src/test/java/net/hostsharing/hsadminng/rbac/rbacuser/RbacUserControllerRestTest.java
Normal file
71
src/test/java/net/hostsharing/hsadminng/rbac/rbacuser/RbacUserControllerRestTest.java
Normal file
@@ -0,0 +1,71 @@
|
||||
package net.hostsharing.hsadminng.rbac.rbacuser;
|
||||
|
||||
import net.hostsharing.hsadminng.context.Context;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import static net.hostsharing.test.IsValidUuidMatcher.isValidUuid;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@WebMvcTest(RbacUserController.class)
|
||||
class RbacUserControllerRestTest {
|
||||
|
||||
@Autowired
|
||||
MockMvc mockMvc;
|
||||
@MockBean
|
||||
Context contextMock;
|
||||
@MockBean
|
||||
RbacUserRepository rbacUserRepository;
|
||||
|
||||
@Test
|
||||
void createUserUsesGivenUuid() throws Exception {
|
||||
// given
|
||||
final var givenUuid = UUID.randomUUID();
|
||||
|
||||
// when
|
||||
mockMvc.perform(MockMvcRequestBuilders
|
||||
.post("/api/rbac-users")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("""
|
||||
{
|
||||
"uuid": "%s"
|
||||
}
|
||||
""".formatted(givenUuid))
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
|
||||
// then
|
||||
.andExpect(status().isCreated())
|
||||
.andExpect(jsonPath("uuid", is(givenUuid.toString())));
|
||||
|
||||
// then
|
||||
verify(rbacUserRepository).create(argThat(entity -> entity.getUuid().equals(givenUuid)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void createUserGeneratesRandomUuidIfNotGiven() throws Exception {
|
||||
// when
|
||||
mockMvc.perform(MockMvcRequestBuilders
|
||||
.post("/api/rbac-users")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("{}")
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
|
||||
// then
|
||||
.andExpect(status().isCreated())
|
||||
.andExpect(jsonPath("uuid", isValidUuid()));
|
||||
|
||||
// then
|
||||
verify(rbacUserRepository).create(argThat(entity -> entity.getUuid() != null));
|
||||
}
|
||||
}
|
37
src/test/java/net/hostsharing/test/IsValidUuidMatcher.java
Normal file
37
src/test/java/net/hostsharing/test/IsValidUuidMatcher.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package net.hostsharing.test;
|
||||
|
||||
import org.hamcrest.BaseMatcher;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class IsValidUuidMatcher extends BaseMatcher<CharSequence> {
|
||||
|
||||
public static Matcher<CharSequence> isValidUuid() {
|
||||
return new IsValidUuidMatcher();
|
||||
}
|
||||
|
||||
public static boolean isValidUuid(final String actual) {
|
||||
try {
|
||||
UUID.fromString(actual);
|
||||
} catch (final IllegalArgumentException exc) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(final Object actual) {
|
||||
if (actual == null || actual.getClass().isAssignableFrom(CharSequence.class)) {
|
||||
return false;
|
||||
}
|
||||
return isValidUuid(actual.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(final Description description) {
|
||||
description.appendText("valid UUID");
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user