Spaces:
Build error
Build error
da-policyengine-dev
/
src
/test
/java
/com
/dalab
/policyengine
/controller
/PolicyControllerTest.java
| package com.dalab.policyengine.controller; | |
| import static org.mockito.ArgumentMatchers.*; | |
| import static org.mockito.Mockito.*; | |
| import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*; | |
| import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; | |
| import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*; | |
| import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; | |
| import java.time.LocalDateTime; | |
| import java.util.*; | |
| import org.junit.jupiter.api.BeforeEach; | |
| 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 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.data.domain.Page; | |
| import org.springframework.data.domain.PageImpl; | |
| import org.springframework.data.domain.PageRequest; | |
| import org.springframework.data.domain.Pageable; | |
| import org.springframework.http.MediaType; | |
| import org.springframework.security.test.context.support.WithMockUser; | |
| import org.springframework.test.context.ActiveProfiles; | |
| import org.springframework.test.web.servlet.MockMvc; | |
| import com.dalab.policyengine.dto.*; | |
| import com.dalab.policyengine.model.Policy; | |
| import com.dalab.policyengine.model.PolicyDraft; | |
| import com.dalab.policyengine.model.PolicyStatus; | |
| import com.dalab.policyengine.service.IPolicyService; | |
| import com.dalab.policyengine.service.IPolicyEvaluationService; | |
| import com.dalab.policyengine.service.IPolicyDraftService; | |
| import com.dalab.policyengine.service.IEventSubscriptionService; | |
| import com.fasterxml.jackson.databind.ObjectMapper; | |
| class PolicyControllerTest { | |
| private MockMvc mockMvc; | |
| private IPolicyService policyService; | |
| private IPolicyEvaluationService policyEvaluationService; | |
| private IPolicyDraftService policyDraftService; | |
| private IEventSubscriptionService eventSubscriptionService; | |
| private ObjectMapper objectMapper; | |
| private Policy testPolicy; | |
| private PolicyDTO testPolicyDTO; | |
| private PolicyDraft testPolicyDraft; | |
| private PolicyDraftDTO testPolicyDraftDTO; | |
| private PolicyEvaluationRequestDTO testEvaluationRequest; | |
| private PolicyImpactRequestDTO testImpactRequest; | |
| private PolicyImpactResponseDTO testImpactResponse; | |
| void setUp() { | |
| // Create test policy | |
| testPolicy = new Policy(); | |
| testPolicy.setId(UUID.randomUUID()); | |
| testPolicy.setName("Test Policy"); | |
| testPolicy.setDescription("Test policy for compliance"); | |
| testPolicy.setRulesContent("when asset.type == 'PII' then tag('SENSITIVE')"); | |
| testPolicy.setStatus(PolicyStatus.ENABLED); | |
| testPolicy.setCreatedAt(LocalDateTime.now()); | |
| testPolicy.setUpdatedAt(LocalDateTime.now()); | |
| // Create test policy DTO | |
| testPolicyDTO = PolicyDTO.builder() | |
| .id(testPolicy.getId()) | |
| .name("Test Policy") | |
| .description("Test policy for compliance") | |
| .rulesContent("when asset.type == 'PII' then tag('SENSITIVE')") | |
| .status("ENABLED") | |
| .createdAt(LocalDateTime.now()) | |
| .updatedAt(LocalDateTime.now()) | |
| .build(); | |
| // Create test policy draft | |
| testPolicyDraft = new PolicyDraft(); | |
| testPolicyDraft.setId(UUID.randomUUID()); | |
| testPolicyDraft.setName("Test Draft Policy"); | |
| testPolicyDraft.setDescription("Draft policy for testing"); | |
| testPolicyDraft.setRulesContent("when asset.type == 'PHI' then tag('HEALTHCARE')"); | |
| testPolicyDraft.setStatus("DRAFT"); | |
| testPolicyDraft.setCreatedAt(LocalDateTime.now()); | |
| // Create test policy draft DTO | |
| testPolicyDraftDTO = PolicyDraftDTO.builder() | |
| .id(testPolicyDraft.getId()) | |
| .name("Test Draft Policy") | |
| .description("Draft policy for testing") | |
| .rulesContent("when asset.type == 'PHI' then tag('HEALTHCARE')") | |
| .status("DRAFT") | |
| .createdAt(LocalDateTime.now()) | |
| .build(); | |
| // Create test evaluation request | |
| testEvaluationRequest = PolicyEvaluationRequestDTO.builder() | |
| .policyId(testPolicy.getId()) | |
| .assetId(UUID.randomUUID()) | |
| .evaluationContext(Map.of("asset.type", "PII")) | |
| .build(); | |
| // Create test impact request | |
| testImpactRequest = PolicyImpactRequestDTO.builder() | |
| .rulesContent("when asset.type == 'PII' then tag('SENSITIVE')") | |
| .analysisType("FULL") | |
| .includePerformanceEstimate(true) | |
| .includeCostImpact(true) | |
| .includeComplianceImpact(true) | |
| .build(); | |
| // Create test impact response | |
| testImpactResponse = PolicyImpactResponseDTO.builder() | |
| .analysisId("impact-12345678") | |
| .analysisType("FULL") | |
| .build(); | |
| } | |
| void createPolicy_AsDataEngineer_ShouldSucceed() throws Exception { | |
| // Given | |
| PolicyCreateRequestDTO request = PolicyCreateRequestDTO.builder() | |
| .name("New Test Policy") | |
| .description("New test policy for compliance") | |
| .rulesContent("when asset.type == 'PII' then tag('SENSITIVE')") | |
| .build(); | |
| when(policyService.createPolicy(any(PolicyCreateRequestDTO.class))).thenReturn(testPolicyDTO); | |
| // When & Then | |
| mockMvc.perform(post("/api/v1/policyengine/policies") | |
| .with(csrf()) | |
| .contentType(MediaType.APPLICATION_JSON) | |
| .content(objectMapper.writeValueAsString(request))) | |
| .andExpect(status().isCreated()) | |
| .andExpect(jsonPath("$.id").value(testPolicy.getId().toString())) | |
| .andExpect(jsonPath("$.name").value("Test Policy")) | |
| .andExpect(jsonPath("$.status").value("ENABLED")); | |
| } | |
| void createPolicy_AsUser_ShouldBeForbidden() throws Exception { | |
| // Given | |
| PolicyCreateRequestDTO request = PolicyCreateRequestDTO.builder() | |
| .name("New Test Policy") | |
| .description("New test policy for compliance") | |
| .rulesContent("when asset.type == 'PII' then tag('SENSITIVE')") | |
| .build(); | |
| // When & Then | |
| mockMvc.perform(post("/api/v1/policyengine/policies") | |
| .with(csrf()) | |
| .contentType(MediaType.APPLICATION_JSON) | |
| .content(objectMapper.writeValueAsString(request))) | |
| .andExpect(status().isForbidden()); | |
| } | |
| void getAllPolicies_AsDataEngineer_ShouldSucceed() throws Exception { | |
| // Given | |
| List<PolicyDTO> policyList = Arrays.asList(testPolicyDTO); | |
| Page<PolicyDTO> policyPage = new PageImpl<>(policyList, PageRequest.of(0, 20), 1); | |
| when(policyService.getAllPolicies(any(Pageable.class))).thenReturn(policyPage); | |
| // When & Then | |
| mockMvc.perform(get("/api/v1/policyengine/policies") | |
| .param("page", "0") | |
| .param("size", "20")) | |
| .andExpect(status().isOk()) | |
| .andExpect(jsonPath("$.content[0].id").value(testPolicy.getId().toString())) | |
| .andExpect(jsonPath("$.content[0].name").value("Test Policy")) | |
| .andExpect(jsonPath("$.totalElements").value(1)); | |
| } | |
| void getPolicyById_AsDataEngineer_ShouldSucceed() throws Exception { | |
| // Given | |
| when(policyService.getPolicyById(testPolicy.getId())).thenReturn(Optional.of(testPolicyDTO)); | |
| // When & Then | |
| mockMvc.perform(get("/api/v1/policyengine/policies/{policyId}", testPolicy.getId())) | |
| .andExpect(status().isOk()) | |
| .andExpect(jsonPath("$.id").value(testPolicy.getId().toString())) | |
| .andExpect(jsonPath("$.name").value("Test Policy")) | |
| .andExpect(jsonPath("$.status").value("ENABLED")); | |
| } | |
| void getPolicyById_PolicyNotFound_ShouldReturnNotFound() throws Exception { | |
| // Given | |
| UUID nonExistentId = UUID.randomUUID(); | |
| when(policyService.getPolicyById(nonExistentId)).thenReturn(Optional.empty()); | |
| // When & Then | |
| mockMvc.perform(get("/api/v1/policyengine/policies/{policyId}", nonExistentId)) | |
| .andExpect(status().isNotFound()); | |
| } | |
| void updatePolicy_AsDataEngineer_ShouldSucceed() throws Exception { | |
| // Given | |
| PolicyUpdateRequestDTO request = PolicyUpdateRequestDTO.builder() | |
| .name("Updated Test Policy") | |
| .description("Updated test policy for compliance") | |
| .rulesContent("when asset.type == 'PII' then tag('SENSITIVE') and notify('admin')") | |
| .status("ENABLED") | |
| .build(); | |
| PolicyDTO updatedPolicy = PolicyDTO.builder() | |
| .id(testPolicy.getId()) | |
| .name("Updated Test Policy") | |
| .description("Updated test policy for compliance") | |
| .rulesContent("when asset.type == 'PII' then tag('SENSITIVE') and notify('admin')") | |
| .status("ENABLED") | |
| .createdAt(LocalDateTime.now()) | |
| .updatedAt(LocalDateTime.now()) | |
| .build(); | |
| when(policyService.updatePolicy(eq(testPolicy.getId()), any(PolicyUpdateRequestDTO.class))) | |
| .thenReturn(updatedPolicy); | |
| // When & Then | |
| mockMvc.perform(put("/api/v1/policyengine/policies/{policyId}", testPolicy.getId()) | |
| .with(csrf()) | |
| .contentType(MediaType.APPLICATION_JSON) | |
| .content(objectMapper.writeValueAsString(request))) | |
| .andExpect(status().isOk()) | |
| .andExpect(jsonPath("$.id").value(testPolicy.getId().toString())) | |
| .andExpect(jsonPath("$.name").value("Updated Test Policy")) | |
| .andExpect(jsonPath("$.status").value("ENABLED")); | |
| } | |
| void deletePolicy_AsDataEngineer_ShouldSucceed() throws Exception { | |
| // Given | |
| doNothing().when(policyService).deletePolicy(testPolicy.getId()); | |
| // When & Then | |
| mockMvc.perform(delete("/api/v1/policyengine/policies/{policyId}", testPolicy.getId()) | |
| .with(csrf())) | |
| .andExpect(status().isNoContent()); | |
| } | |
| void deletePolicy_AsUser_ShouldBeForbidden() throws Exception { | |
| // When & Then | |
| mockMvc.perform(delete("/api/v1/policyengine/policies/{policyId}", testPolicy.getId()) | |
| .with(csrf())) | |
| .andExpect(status().isForbidden()); | |
| } | |
| void evaluatePolicy_AsDataEngineer_ShouldSucceed() throws Exception { | |
| // Given | |
| PolicyEvaluationResponseDTO evaluationResponse = PolicyEvaluationResponseDTO.builder() | |
| .policyId(testPolicy.getId()) | |
| .assetId(testEvaluationRequest.getAssetId()) | |
| .evaluationResult("PASS") | |
| .actions(Arrays.asList("tag('SENSITIVE')")) | |
| .evaluationTimestamp(LocalDateTime.now()) | |
| .build(); | |
| when(policyEvaluationService.evaluatePolicy(any(PolicyEvaluationRequestDTO.class))) | |
| .thenReturn(evaluationResponse); | |
| // When & Then | |
| mockMvc.perform(post("/api/v1/policyengine/policies/evaluate") | |
| .with(csrf()) | |
| .contentType(MediaType.APPLICATION_JSON) | |
| .content(objectMapper.writeValueAsString(testEvaluationRequest))) | |
| .andExpect(status().isOk()) | |
| .andExpect(jsonPath("$.policyId").value(testPolicy.getId().toString())) | |
| .andExpect(jsonPath("$.evaluationResult").value("PASS")); | |
| } | |
| void analyzePolicyImpact_AsDataEngineer_ShouldSucceed() throws Exception { | |
| // Given | |
| when(policyService.analyzePolicy(any(PolicyImpactRequestDTO.class))) | |
| .thenReturn(testImpactResponse); | |
| // When & Then | |
| mockMvc.perform(post("/api/v1/policyengine/policies/{policyId}/impact-preview", testPolicy.getId()) | |
| .with(csrf()) | |
| .contentType(MediaType.APPLICATION_JSON) | |
| .content(objectMapper.writeValueAsString(testImpactRequest))) | |
| .andExpect(status().isOk()) | |
| .andExpect(jsonPath("$.analysisId").value("impact-12345678")) | |
| .andExpect(jsonPath("$.analysisType").value("FULL")); | |
| } | |
| void createPolicyDraft_AsDataEngineer_ShouldSucceed() throws Exception { | |
| // Given | |
| PolicyDraftCreateRequestDTO request = PolicyDraftCreateRequestDTO.builder() | |
| .name("New Draft Policy") | |
| .description("New draft policy for testing") | |
| .rulesContent("when asset.type == 'PHI' then tag('HEALTHCARE')") | |
| .build(); | |
| when(policyDraftService.createPolicyDraft(any(PolicyDraftCreateRequestDTO.class))) | |
| .thenReturn(testPolicyDraftDTO); | |
| // When & Then | |
| mockMvc.perform(post("/api/v1/policyengine/policies/drafts") | |
| .with(csrf()) | |
| .contentType(MediaType.APPLICATION_JSON) | |
| .content(objectMapper.writeValueAsString(request))) | |
| .andExpect(status().isCreated()) | |
| .andExpect(jsonPath("$.id").value(testPolicyDraft.getId().toString())) | |
| .andExpect(jsonPath("$.name").value("Test Draft Policy")) | |
| .andExpect(jsonPath("$.status").value("DRAFT")); | |
| } | |
| void getAllPolicyDrafts_AsDataEngineer_ShouldSucceed() throws Exception { | |
| // Given | |
| List<PolicyDraftDTO> draftList = Arrays.asList(testPolicyDraftDTO); | |
| Page<PolicyDraftDTO> draftPage = new PageImpl<>(draftList, PageRequest.of(0, 20), 1); | |
| when(policyDraftService.getAllPolicyDrafts(any(Pageable.class))).thenReturn(draftPage); | |
| // When & Then | |
| mockMvc.perform(get("/api/v1/policyengine/policies/drafts") | |
| .param("page", "0") | |
| .param("size", "20")) | |
| .andExpect(status().isOk()) | |
| .andExpect(jsonPath("$.content[0].id").value(testPolicyDraft.getId().toString())) | |
| .andExpect(jsonPath("$.content[0].name").value("Test Draft Policy")) | |
| .andExpect(jsonPath("$.totalElements").value(1)); | |
| } | |
| void getPolicyDraftById_AsDataEngineer_ShouldSucceed() throws Exception { | |
| // Given | |
| when(policyDraftService.getPolicyDraftById(testPolicyDraft.getId())) | |
| .thenReturn(Optional.of(testPolicyDraftDTO)); | |
| // When & Then | |
| mockMvc.perform(get("/api/v1/policyengine/policies/drafts/{draftId}", testPolicyDraft.getId())) | |
| .andExpect(status().isOk()) | |
| .andExpect(jsonPath("$.id").value(testPolicyDraft.getId().toString())) | |
| .andExpect(jsonPath("$.name").value("Test Draft Policy")) | |
| .andExpect(jsonPath("$.status").value("DRAFT")); | |
| } | |
| void updatePolicyDraft_AsDataEngineer_ShouldSucceed() throws Exception { | |
| // Given | |
| PolicyDraftUpdateRequestDTO request = PolicyDraftUpdateRequestDTO.builder() | |
| .name("Updated Draft Policy") | |
| .description("Updated draft policy for testing") | |
| .rulesContent("when asset.type == 'PHI' then tag('HEALTHCARE') and encrypt()") | |
| .build(); | |
| PolicyDraftDTO updatedDraft = PolicyDraftDTO.builder() | |
| .id(testPolicyDraft.getId()) | |
| .name("Updated Draft Policy") | |
| .description("Updated draft policy for testing") | |
| .rulesContent("when asset.type == 'PHI' then tag('HEALTHCARE') and encrypt()") | |
| .status("DRAFT") | |
| .createdAt(LocalDateTime.now()) | |
| .updatedAt(LocalDateTime.now()) | |
| .build(); | |
| when(policyDraftService.updatePolicyDraft(eq(testPolicyDraft.getId()), any(PolicyDraftUpdateRequestDTO.class))) | |
| .thenReturn(updatedDraft); | |
| // When & Then | |
| mockMvc.perform(put("/api/v1/policyengine/policies/drafts/{draftId}", testPolicyDraft.getId()) | |
| .with(csrf()) | |
| .contentType(MediaType.APPLICATION_JSON) | |
| .content(objectMapper.writeValueAsString(request))) | |
| .andExpect(status().isOk()) | |
| .andExpect(jsonPath("$.id").value(testPolicyDraft.getId().toString())) | |
| .andExpect(jsonPath("$.name").value("Updated Draft Policy")); | |
| } | |
| void approvePolicyDraft_AsDataEngineer_ShouldSucceed() throws Exception { | |
| // Given | |
| PolicyDraftApprovalRequestDTO request = PolicyDraftApprovalRequestDTO.builder() | |
| .approved(true) | |
| .comments("Approved for production use") | |
| .build(); | |
| PolicyDTO approvedPolicy = PolicyDTO.builder() | |
| .id(UUID.randomUUID()) | |
| .name("Approved Policy") | |
| .description("Policy approved from draft") | |
| .rulesContent("when asset.type == 'PHI' then tag('HEALTHCARE')") | |
| .status("ENABLED") | |
| .createdAt(LocalDateTime.now()) | |
| .updatedAt(LocalDateTime.now()) | |
| .build(); | |
| when(policyDraftService.approvePolicyDraft(eq(testPolicyDraft.getId()), any(PolicyDraftApprovalRequestDTO.class))) | |
| .thenReturn(approvedPolicy); | |
| // When & Then | |
| mockMvc.perform(post("/api/v1/policyengine/policies/drafts/{draftId}/approve", testPolicyDraft.getId()) | |
| .with(csrf()) | |
| .contentType(MediaType.APPLICATION_JSON) | |
| .content(objectMapper.writeValueAsString(request))) | |
| .andExpect(status().isOk()) | |
| .andExpect(jsonPath("$.name").value("Approved Policy")) | |
| .andExpect(jsonPath("$.status").value("ENABLED")); | |
| } | |
| void createPolicy_InvalidRequest_ShouldReturnBadRequest() throws Exception { | |
| // Given | |
| PolicyCreateRequestDTO request = PolicyCreateRequestDTO.builder() | |
| .name("") // Invalid: empty name | |
| .description("Test policy") | |
| .rulesContent("invalid rule syntax") | |
| .build(); | |
| // When & Then | |
| mockMvc.perform(post("/api/v1/policyengine/policies") | |
| .with(csrf()) | |
| .contentType(MediaType.APPLICATION_JSON) | |
| .content(objectMapper.writeValueAsString(request))) | |
| .andExpect(status().isBadRequest()); | |
| } | |
| void evaluatePolicy_InvalidRequest_ShouldReturnBadRequest() throws Exception { | |
| // Given | |
| PolicyEvaluationRequestDTO request = PolicyEvaluationRequestDTO.builder() | |
| .policyId(null) // Invalid: null policy ID | |
| .assetId(UUID.randomUUID()) | |
| .evaluationContext(Map.of("asset.type", "PII")) | |
| .build(); | |
| // When & Then | |
| mockMvc.perform(post("/api/v1/policyengine/policies/evaluate") | |
| .with(csrf()) | |
| .contentType(MediaType.APPLICATION_JSON) | |
| .content(objectMapper.writeValueAsString(request))) | |
| .andExpect(status().isBadRequest()); | |
| } | |
| void analyzePolicyImpact_InvalidRequest_ShouldReturnBadRequest() throws Exception { | |
| // Given | |
| PolicyImpactRequestDTO request = PolicyImpactRequestDTO.builder() | |
| .rulesContent("") // Invalid: empty rules content | |
| .analysisType("INVALID_TYPE") // Invalid: unknown analysis type | |
| .build(); | |
| // When & Then | |
| mockMvc.perform(post("/api/v1/policyengine/policies/{policyId}/impact-preview", testPolicy.getId()) | |
| .with(csrf()) | |
| .contentType(MediaType.APPLICATION_JSON) | |
| .content(objectMapper.writeValueAsString(request))) | |
| .andExpect(status().isBadRequest()); | |
| } | |
| } |