Skip to content

Commit

Permalink
base initial integration tests (#218)
Browse files Browse the repository at this point in the history
* Initial Integration test setup, need to persist service gen entities

* Now using jsonunit

* Basic CRUD tests for GroupController

* Cleanup

* More complete delete test and todos for future tests

* New Google formatter in acton

* WIP Contribution guidelines

* Too soon
  • Loading branch information
lepsalex committed Dec 11, 2018
1 parent 928c7ac commit 2b95ebc
Show file tree
Hide file tree
Showing 3 changed files with 308 additions and 0 deletions.
48 changes: 48 additions & 0 deletions CONTRIBUTING.md
@@ -0,0 +1,48 @@
# Contributing

When contributing to this repository, please first discuss the change you wish to make via issue,
email, or any other method with the owners of this repository before making a change.

Please note we have a code of conduct, please follow it in all your interactions with the project.

## Code Standards

#### General
1. Do not use field injection (ie. `@Value`, `@Autowired`)
- Instead use an `@Autowired` or `@Value` annotated constructor
- This helps to improves testability
- Helps to decouple from Spring
- If your constructor is feeling messy or too big - you are probably overloading the class you are working on
2. If a class is dependent on more than 3 constructor arguments, a _single_ config class should encapsulate those arguments while
implementing a builder pattern (ie. Lombok `@Builder` annotation)
3. Do not use any implementation specific JPA code (ie. Hibernate-only annotations)
- Exception for when no alternative functionality exists (ie. Postgres JSON field search)
4. All of our code is auto-formatted to Google Java Format using the [fmt-maven-plugin](https://mvnrepository.com/artifact/com.coveo/fmt-maven-plugin) on build:
```xml
<plugin>
<groupId>com.coveo</groupId>
<artifactId>fmt-maven-plugin</artifactId>
<version>${FMT_MVN_PLG.VERSION}</version>
<executions>
<execution>
<goals>
<goal>format</goal>
</goals>
</execution>
</executions>
</plugin>
```

#### Service Layer
1. Get * should always return Optional<T>
2. Find * should always return a Collection<T>

### Testing

#### General
1. DB via Test Containers - no in-memory DB or OS specific services
2. No dependencies on any external services (ie. production micro-service)

##### Unit Testing

##### Integration Testing
8 changes: 8 additions & 0 deletions pom.xml
Expand Up @@ -158,6 +158,14 @@
<version>2.9.5</version>
</dependency>

<!-- JSON Testing -->
<dependency>
<groupId>net.javacrumbs.json-unit</groupId>
<artifactId>json-unit-fluent</artifactId>
<version>2.1.1</version>
<scope>test</scope>
</dependency>

<!-- Vault -->
<dependency>
<groupId>org.springframework.cloud</groupId>
Expand Down
252 changes: 252 additions & 0 deletions src/test/java/bio/overture/ego/controller/GroupControllerTest.java
@@ -0,0 +1,252 @@
package bio.overture.ego.controller;

import bio.overture.ego.AuthorizationServiceMain;
import bio.overture.ego.model.entity.Group;
import bio.overture.ego.service.GroupService;
import bio.overture.ego.service.UserService;
import bio.overture.ego.utils.EntityGenerator;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.json.JSONException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.http.*;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.UUID;

import static bio.overture.ego.utils.CollectionUtils.listOf;
import static net.javacrumbs.jsonunit.core.Option.IGNORING_ARRAY_ORDER;
import static net.javacrumbs.jsonunit.core.Option.IGNORING_EXTRA_ARRAY_ITEMS;
import static net.javacrumbs.jsonunit.fluent.JsonFluentAssert.assertThatJson;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;

@Slf4j
@ActiveProfiles("test")
@RunWith(SpringRunner.class)
@SpringBootTest(
classes = AuthorizationServiceMain.class,
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class GroupControllerTest {

@LocalServerPort private int port;
private TestRestTemplate restTemplate = new TestRestTemplate();
private HttpHeaders headers = new HttpHeaders();

private static boolean hasRunEntitySetup = false;

@Autowired private EntityGenerator entityGenerator;
@Autowired private GroupService groupService;
@Autowired private UserService userService;

@Before
public void Setup() {

// Initial setup of entities (run once
if (!hasRunEntitySetup) {
entityGenerator.setupTestUsers();
entityGenerator.setupTestApplications();
entityGenerator.setupTestGroups();
hasRunEntitySetup = true;
}

headers.add("Authorization", "Bearer TestToken");
headers.setContentType(MediaType.APPLICATION_JSON);
}

@Test
public void AddGroup() {

Group group = new Group("Wizards");

HttpEntity<Group> entity = new HttpEntity<Group>(group, headers);

ResponseEntity<String> response =
restTemplate.exchange(createURLWithPort("/groups"), HttpMethod.POST, entity, String.class);

HttpStatus responseStatus = response.getStatusCode();
assertEquals(HttpStatus.OK, responseStatus);
}

@Test
public void AddUniqueGroup() {

entityGenerator.setupGroup("SameSame");
Group group = new Group("SameSame");

HttpEntity<Group> entity = new HttpEntity<Group>(group, headers);

ResponseEntity<String> response =
restTemplate.exchange(createURLWithPort("/groups"), HttpMethod.POST, entity, String.class);

HttpStatus responseStatus = response.getStatusCode();
assertEquals(HttpStatus.CONFLICT, responseStatus); // TODO
}

@Test
public void GetGroup() throws JSONException {

// Groups created in setup
val groupId = groupService.getByName("Group One").getId();

HttpEntity<String> entity = new HttpEntity<String>(null, headers);

ResponseEntity<String> response =
restTemplate.exchange(
createURLWithPort(String.format("/groups/%s", groupId)),
HttpMethod.GET,
entity,
String.class);

HttpStatus responseStatus = response.getStatusCode();
String responseBody = response.getBody();

String expected =
String.format(
"{\"id\":\"%s\",\"name\":\"Group One\",\"description\":null,\"status\":null}", groupId);

assertEquals(HttpStatus.OK, responseStatus);
assertThatJson(responseBody).isEqualTo(expected);
}

@Test
public void GetGroupNotFound() throws JSONException {
HttpEntity<String> entity = new HttpEntity<String>(null, headers);

ResponseEntity<String> response =
restTemplate.exchange(
createURLWithPort(String.format("/groups/%s", UUID.randomUUID())),
HttpMethod.GET,
entity,
String.class);

HttpStatus responseStatus = response.getStatusCode();

assertEquals(HttpStatus.NOT_FOUND, responseStatus); // TODO
}

@Test
public void ListGroups() throws JSONException {
HttpEntity<String> entity = new HttpEntity<String>(null, headers);

ResponseEntity<String> response =
restTemplate.exchange(createURLWithPort("/groups"), HttpMethod.GET, entity, String.class);

HttpStatus responseStatus = response.getStatusCode();
String responseBody = response.getBody();

String expected =
String.format(
"[{\"id\":\"%s\",\"name\":\"Group One\",\"description\":null,\"status\":null}, {\"id\":\"%s\",\"name\":\"Group Two\",\"description\":null,\"status\":null}, {\"id\":\"%s\",\"name\":\"Group Three\",\"description\":null,\"status\":null}]",
groupService.getByName("Group One").getId(),
groupService.getByName("Group Two").getId(),
groupService.getByName("Group Three").getId());

assertEquals(HttpStatus.OK, responseStatus);
assertThatJson(responseBody)
.when(IGNORING_EXTRA_ARRAY_ITEMS, IGNORING_ARRAY_ORDER)
.node("resultSet")
.isEqualTo(expected);
}

// TODO - ADD List/Filter tests

@Test
public void UpdateGroup() {

// Groups created in setup
val groupId = entityGenerator.setupGroup("Complete").getId();

Group update = new Group("Updated Complete");
update.setId(groupId);

HttpEntity<Group> entity = new HttpEntity<Group>(update, headers);

ResponseEntity<String> response =
restTemplate.exchange(
createURLWithPort(String.format("/groups/%s", groupId)),
HttpMethod.PUT,
entity,
String.class);

String responseBody = response.getBody();

HttpStatus responseStatus = response.getStatusCode();
assertEquals(HttpStatus.OK, responseStatus);
assertThatJson(responseBody).node("id").isEqualTo(groupId);
assertThatJson(responseBody).node("name").isEqualTo("Updated Complete");
}

// TODO - ADD Update non-existent entity

@Test
public void PartialUpdateGroup() throws JSONException {

// Groups created in setup
val groupId = entityGenerator.setupGroup("Partial").getId();

val update = "{\"name\":\"Updated Partial\"}";
HttpEntity<String> entity = new HttpEntity<String>(update, headers);

ResponseEntity<String> response =
restTemplate.exchange(
createURLWithPort(String.format("/groups/%s", groupId)),
HttpMethod.PATCH,
entity,
String.class); // TODO - No Patch Method

String responseBody = response.getBody();

HttpStatus responseStatus = response.getStatusCode();
assertEquals(HttpStatus.OK, responseStatus);
assertThatJson(responseBody).node("id").isEqualTo(groupId);
assertThatJson(responseBody).node("name").isEqualTo("Updated Partial");
}

@Test
public void DeleteOne() throws JSONException {

// Groups created in setup
val groupId = entityGenerator.setupGroup("Temporary").getId();

// Add a user to this group
userService.addUserToGroups(
userService.getByName("FirstUser@domain.com").getId().toString(),
listOf(groupId.toString()));

// TODO - ADD application groups relationship

HttpEntity<String> entity = new HttpEntity<String>(null, headers);

ResponseEntity<String> response =
restTemplate.exchange(
createURLWithPort(String.format("/groups/%s", groupId)),
HttpMethod.DELETE,
entity,
String.class);

HttpStatus responseStatus = response.getStatusCode();

// Check http response
assertEquals(HttpStatus.OK, responseStatus);

// Check user-group relationship is also deleted
assertNotEquals(null, userService.getByName("FirstUser@domain.com"));

// Check group is deleted
assertEquals(null, groupService.getByName("Temporary"));
}

// TODO - ADD tests for adding user/apps to groups

private String createURLWithPort(String uri) {
return "http://localhost:" + port + uri;
}
}

0 comments on commit 2b95ebc

Please sign in to comment.