Skip to content

Commit

Permalink
Add first test with TestContainers
Browse files Browse the repository at this point in the history
  • Loading branch information
fjhdream committed Jun 18, 2023
1 parent c9e2e26 commit 586e968
Show file tree
Hide file tree
Showing 8 changed files with 203 additions and 0 deletions.
15 changes: 15 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
Expand Down Expand Up @@ -69,6 +73,17 @@
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
<version>1.17.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-testcontainers</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

import com.fasterxml.jackson.annotation.JsonAlias;
import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class UserRequest {

@NotBlank(message = "User ID can not be empty!")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.fjhdream.truckbilling;

import org.springframework.boot.devtools.restart.RestartScope;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.context.annotation.Bean;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.utility.DockerImageName;

@org.springframework.boot.test.context.TestConfiguration(proxyBeanMethods = false)
public class TestContainerConfiguration {

@Bean
@ServiceConnection
@RestartScope
public PostgreSQLContainer<?> postgreSQLContainer() {
return new PostgreSQLContainer(DockerImageName.parse("postgres:15.1"))
.withUsername("testUser")
.withPassword("testSecret")
.withDatabaseName("testDatabase");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@

import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
@Import(TestContainerConfiguration.class)
class TruckBillingApplicationTests {

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.fjhdream.truckbilling.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fjhdream.truckbilling.TestContainerConfiguration;
import com.fjhdream.truckbilling.controller.entity.request.UserRequest;
import com.fjhdream.truckbilling.service.wx.WxService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;


@SpringBootTest
@AutoConfigureMockMvc
@Import(TestContainerConfiguration.class)
class UserControllerTest {

@Autowired
MockMvc mockMvc;

@MockBean
WxService wxService;

public static String asJsonString(final Object obj) {
try {
return new ObjectMapper().writeValueAsString(obj);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

@Test
void create_user_and_succeed() throws Exception {
this.mockMvc.perform(post("/user")
.content(asJsonString(new UserRequest("test_user_id", "test_user_name", "test_avatar_url")))
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
).andExpect(status().isCreated());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.fjhdream.truckbilling.service.user;

import com.fjhdream.truckbilling.TestContainerConfiguration;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.server.ResponseStatusException;

@RunWith(SpringRunner.class)
@SpringBootTest
@Import(TestContainerConfiguration.class)
class UserServiceTest {

@Autowired
private UserService userService;

@Test
public void check_not_exist_user() {
Assertions.assertThrows(ResponseStatusException.class, () -> {
userService.checkUser("not_exist_user");
});
}
}
4 changes: 4 additions & 0 deletions src/test/resources/application.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
spring.datasource.driver-class-name=org.testcontainers.jdbc.ContainerDatabaseDriver
spring.jpa.hibernate.ddl-auto=create
truck.app-id=testAppId
truck.app-secret=testAppSecret
83 changes: 83 additions & 0 deletions src/test/resources/schema.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
CREATE TABLE "user"
(
id VARCHAR(128) PRIMARY KEY,
user_name VARCHAR(128) NOT NULL,
avatar_url text
);

CREATE TYPE role_type AS ENUM ('OWNER', 'ADMIN', 'DRIVER');
CREATE TABLE role
(
id uuid PRIMARY KEY,
user_id VARCHAR(128) NOT NULL REFERENCES "user" (id),
type role_type NOT NULL,
UNIQUE (user_id, "type")
);

CREATE TABLE team
(
id uuid PRIMARY KEY,
team_name VARCHAR(128) NOT NULL,
user_id VARCHAR(128) NOT NULL REFERENCES "user" (id)
);

CREATE TYPE use_status AS ENUM ('INUSE', 'DELETED');

CREATE TABLE team_car
(
id uuid PRIMARY KEY,
team_id uuid NOT NULL REFERENCES team (id),
car_plate_number VARCHAR(128) NOT NULL,
status use_status NOT NULL
);

CREATE TABLE team_driver
(
id uuid PRIMARY KEY,
user_id VARCHAR(128) NOT NULL REFERENCES "user" (id),
team_id uuid NOT NULL REFERENCES team (id),
status use_status NOT NULL,
UNIQUE (user_id, team_id)
);

CREATE TYPE item_type as ENUM ('BASIC', 'COSTOM', 'DEFAULT');
CREATE TABLE item
(
id uuid PRIMARY KEY,
type item_type NOT NULL,
name VARCHAR(128) NOT NULL,
team_id uuid REFERENCES team (id),
icon_url text
);

CREATE TYPE billing_status as ENUM ('INITIALIZED', 'STARTED', 'ENDED', 'CLOSED');

CREATE TABLE billing
(
id uuid PRIMARY KEY,
name VARCHAR(128) NOT NULL,
team_id uuid REFERENCES team (id),
start_time TIMESTAMP,
end_time TIMESTAMP,
status billing_status NOT NULL,
commodity VARCHAR(128),
start_location VARCHAR(128),
end_location VARCHAR(128),
start_money money,
end_money money,
team_car_id uuid REFERENCES team_car (id)
);

CREATE TABLE billing_item
(
id uuid PRIMARY KEY,
billing_id uuid REFERENCES billing (id),
cost money CHECK (cost > 0 :: money) NOT NULL,
item_id uuid REFERENCES item (id),
time TIMESTAMP NOT NULL
);

CREATE CAST (varchar AS billing_status) WITH INOUT AS IMPLICIT;
CREATE CAST (varchar AS item_type) WITH INOUT AS IMPLICIT;
CREATE CAST (varchar AS role_type) WITH INOUT AS IMPLICIT;
CREATE CAST (varchar AS use_status) WITH INOUT AS IMPLICIT;

0 comments on commit 586e968

Please sign in to comment.