Spaces:
Sleeping
Sleeping
KevanSoon
commited on
Commit
·
ec4d503
1
Parent(s):
52e8df6
Added Database connection
Browse files- README.md +104 -4
- pom.xml +5 -0
- src/main/java/com/cs102/attendance/TestController.java +0 -13
- src/main/java/com/cs102/attendance/controller/HealthController.java +49 -0
- src/main/java/com/cs102/attendance/controller/TestController.java +75 -0
- src/main/java/com/cs102/attendance/entity/TestConnection.java +53 -0
- src/main/java/com/cs102/attendance/repository/TestConnectionRepository.java +13 -0
- src/main/resources/application.yml +12 -7
- src/test/java/com/cs102/attendance/Cs102AttendanceProjectApplicationTests.java +37 -0
- src/test/java/com/cs102/attendance/controller/TestControllerTest.java +73 -0
README.md
CHANGED
|
@@ -1,4 +1,104 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# CS102 Smart Attendance Project
|
| 2 |
+
|
| 3 |
+
A backend Spring Boot application for a smart attendance tracking system.
|
| 4 |
+
|
| 5 |
+
## ⚙️ Configuration
|
| 6 |
+
|
| 7 |
+
### Environment Variables
|
| 8 |
+
|
| 9 |
+
Create a `.env` file in the project root or set the following environment variables:
|
| 10 |
+
|
| 11 |
+
```env
|
| 12 |
+
# Database Configuration
|
| 13 |
+
SPRING_DATASOURCE_URL=your_url
|
| 14 |
+
SPRING_DATASOURCE_USERNAME=your_username
|
| 15 |
+
SPRING_DATASOURCE_PASSWORD=your_password
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
## 🚀 Running the Application
|
| 19 |
+
|
| 20 |
+
### Using Maven Wrapper (Recommended)
|
| 21 |
+
|
| 22 |
+
```bash
|
| 23 |
+
# On Unix/Linux/macOS
|
| 24 |
+
./mvnw spring-boot:run
|
| 25 |
+
|
| 26 |
+
# On Windows
|
| 27 |
+
mvnw.cmd spring-boot:run
|
| 28 |
+
```
|
| 29 |
+
|
| 30 |
+
### Using Maven
|
| 31 |
+
|
| 32 |
+
```bash
|
| 33 |
+
# Clean and install dependencies
|
| 34 |
+
mvn clean install
|
| 35 |
+
|
| 36 |
+
# Run the application
|
| 37 |
+
mvn spring-boot:run
|
| 38 |
+
```
|
| 39 |
+
|
| 40 |
+
### Using JAR file
|
| 41 |
+
|
| 42 |
+
```bash
|
| 43 |
+
# Build the JAR file
|
| 44 |
+
mvn clean package
|
| 45 |
+
|
| 46 |
+
# Run the JAR file
|
| 47 |
+
java -jar target/attendance-0.0.1-SNAPSHOT.jar
|
| 48 |
+
```
|
| 49 |
+
|
| 50 |
+
The application will start on `http://localhost:8080` by default.
|
| 51 |
+
|
| 52 |
+
### Accessing the Application
|
| 53 |
+
|
| 54 |
+
When you run the application locally, you'll be redirected to a login page due to Spring Security being enabled.
|
| 55 |
+
|
| 56 |
+
**Login Credentials:**
|
| 57 |
+
- **Username:** `user`
|
| 58 |
+
- **Password:** A new password is generated every time you run the project (check your terminal/console output)
|
| 59 |
+
|
| 60 |
+
The generated password will appear in the logs like this:
|
| 61 |
+
```
|
| 62 |
+
Using generated security password: a1b2c3d4-e5f6-7890-abcd-ef1234567890
|
| 63 |
+
```
|
| 64 |
+
|
| 65 |
+
Copy this password from your terminal to log into the application.
|
| 66 |
+
|
| 67 |
+
## 🔗 Application Monitoring
|
| 68 |
+
|
| 69 |
+
The application includes Spring Boot Actuator for basic monitoring:
|
| 70 |
+
|
| 71 |
+
- **Application Health**: `GET /actuator/health`
|
| 72 |
+
- **Application Info**: `GET /actuator/info`
|
| 73 |
+
- **Metrics**: `GET /actuator/metrics`
|
| 74 |
+
- **Prometheus Metrics**: `GET /actuator/prometheus`
|
| 75 |
+
|
| 76 |
+
## 🧪 Testing
|
| 77 |
+
|
| 78 |
+
### Run Unit Tests
|
| 79 |
+
|
| 80 |
+
```bash
|
| 81 |
+
# Using Maven Wrapper
|
| 82 |
+
./mvnw test
|
| 83 |
+
|
| 84 |
+
# Using Maven
|
| 85 |
+
mvn test
|
| 86 |
+
```
|
| 87 |
+
|
| 88 |
+
### Run Integration Tests
|
| 89 |
+
|
| 90 |
+
```bash
|
| 91 |
+
# Using Maven Wrapper
|
| 92 |
+
./mvnw verify
|
| 93 |
+
|
| 94 |
+
# Using Maven
|
| 95 |
+
mvn verify
|
| 96 |
+
```
|
| 97 |
+
|
| 98 |
+
## 🤝 Contributing
|
| 99 |
+
|
| 100 |
+
1. Fork the repository
|
| 101 |
+
2. Create a feature branch: `git checkout -b feature/amazing-feature`
|
| 102 |
+
3. Commit your changes: `git commit -m 'Add some amazing feature'`
|
| 103 |
+
4. Push to the branch: `git push origin feature/amazing-feature`
|
| 104 |
+
5. Open a Pull Request
|
pom.xml
CHANGED
|
@@ -67,6 +67,11 @@
|
|
| 67 |
<artifactId>postgresql</artifactId>
|
| 68 |
<scope>runtime</scope>
|
| 69 |
</dependency>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 70 |
</dependencies>
|
| 71 |
|
| 72 |
<build>
|
|
|
|
| 67 |
<artifactId>postgresql</artifactId>
|
| 68 |
<scope>runtime</scope>
|
| 69 |
</dependency>
|
| 70 |
+
<dependency>
|
| 71 |
+
<groupId>me.paulschwarz</groupId>
|
| 72 |
+
<artifactId>spring-dotenv</artifactId>
|
| 73 |
+
<version>4.0.0</version>
|
| 74 |
+
</dependency>
|
| 75 |
</dependencies>
|
| 76 |
|
| 77 |
<build>
|
src/main/java/com/cs102/attendance/TestController.java
DELETED
|
@@ -1,13 +0,0 @@
|
|
| 1 |
-
package com.cs102.attendance;
|
| 2 |
-
|
| 3 |
-
import org.springframework.web.bind.annotation.GetMapping;
|
| 4 |
-
import org.springframework.web.bind.annotation.RestController;
|
| 5 |
-
|
| 6 |
-
@RestController
|
| 7 |
-
public class TestController {
|
| 8 |
-
|
| 9 |
-
@GetMapping("/hello")
|
| 10 |
-
public String hello() {
|
| 11 |
-
return "Spring Boot is working!";
|
| 12 |
-
}
|
| 13 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/main/java/com/cs102/attendance/controller/HealthController.java
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.cs102.attendance.controller;
|
| 2 |
+
|
| 3 |
+
import org.springframework.beans.factory.annotation.Autowired;
|
| 4 |
+
import org.springframework.http.ResponseEntity;
|
| 5 |
+
import org.springframework.web.bind.annotation.GetMapping;
|
| 6 |
+
import org.springframework.web.bind.annotation.RequestMapping;
|
| 7 |
+
import org.springframework.web.bind.annotation.RestController;
|
| 8 |
+
|
| 9 |
+
import javax.sql.DataSource;
|
| 10 |
+
import java.sql.Connection;
|
| 11 |
+
import java.sql.SQLException;
|
| 12 |
+
import java.util.HashMap;
|
| 13 |
+
import java.util.Map;
|
| 14 |
+
|
| 15 |
+
@RestController
|
| 16 |
+
@RequestMapping("/api/health")
|
| 17 |
+
public class HealthController {
|
| 18 |
+
|
| 19 |
+
@Autowired
|
| 20 |
+
private DataSource dataSource;
|
| 21 |
+
|
| 22 |
+
@GetMapping("/database")
|
| 23 |
+
public ResponseEntity<Map<String, Object>> checkDatabaseConnection() {
|
| 24 |
+
Map<String, Object> response = new HashMap<>();
|
| 25 |
+
|
| 26 |
+
try (Connection connection = dataSource.getConnection()) {
|
| 27 |
+
// Test the connection
|
| 28 |
+
boolean isValid = connection.isValid(5); // 5 second timeout
|
| 29 |
+
|
| 30 |
+
if (isValid) {
|
| 31 |
+
response.put("status", "UP");
|
| 32 |
+
response.put("database", "Connected");
|
| 33 |
+
response.put("url", connection.getMetaData().getURL());
|
| 34 |
+
response.put("driver", connection.getMetaData().getDriverName());
|
| 35 |
+
response.put("version", connection.getMetaData().getDatabaseProductVersion());
|
| 36 |
+
return ResponseEntity.ok(response);
|
| 37 |
+
} else {
|
| 38 |
+
response.put("status", "DOWN");
|
| 39 |
+
response.put("database", "Connection invalid");
|
| 40 |
+
return ResponseEntity.status(503).body(response);
|
| 41 |
+
}
|
| 42 |
+
} catch (SQLException e) {
|
| 43 |
+
response.put("status", "DOWN");
|
| 44 |
+
response.put("database", "Connection failed");
|
| 45 |
+
response.put("error", e.getMessage());
|
| 46 |
+
return ResponseEntity.status(503).body(response);
|
| 47 |
+
}
|
| 48 |
+
}
|
| 49 |
+
}
|
src/main/java/com/cs102/attendance/controller/TestController.java
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.cs102.attendance.controller;
|
| 2 |
+
|
| 3 |
+
import com.cs102.attendance.entity.TestConnection;
|
| 4 |
+
import com.cs102.attendance.repository.TestConnectionRepository;
|
| 5 |
+
import org.springframework.beans.factory.annotation.Autowired;
|
| 6 |
+
import org.springframework.http.ResponseEntity;
|
| 7 |
+
import org.springframework.web.bind.annotation.*;
|
| 8 |
+
|
| 9 |
+
import java.util.HashMap;
|
| 10 |
+
import java.util.List;
|
| 11 |
+
import java.util.Map;
|
| 12 |
+
|
| 13 |
+
@RestController
|
| 14 |
+
@RequestMapping("/api/test")
|
| 15 |
+
public class TestController {
|
| 16 |
+
|
| 17 |
+
@Autowired
|
| 18 |
+
private TestConnectionRepository testConnectionRepository;
|
| 19 |
+
|
| 20 |
+
@GetMapping("/database-operations")
|
| 21 |
+
public ResponseEntity<Map<String, Object>> testDatabaseOperations() {
|
| 22 |
+
Map<String, Object> response = new HashMap<>();
|
| 23 |
+
|
| 24 |
+
try {
|
| 25 |
+
// Test 1: Simple query
|
| 26 |
+
Integer queryResult = testConnectionRepository.testQuery();
|
| 27 |
+
response.put("simpleQuery", queryResult == 1 ? "PASS" : "FAIL");
|
| 28 |
+
|
| 29 |
+
// Test 2: Insert operation
|
| 30 |
+
TestConnection testEntity = new TestConnection("Connection test from Spring Boot");
|
| 31 |
+
TestConnection saved = testConnectionRepository.save(testEntity);
|
| 32 |
+
response.put("insertOperation", saved.getId() != null ? "PASS" : "FAIL");
|
| 33 |
+
|
| 34 |
+
// Test 3: Read operation
|
| 35 |
+
List<TestConnection> allRecords = testConnectionRepository.findAll();
|
| 36 |
+
response.put("readOperation", !allRecords.isEmpty() ? "PASS" : "FAIL");
|
| 37 |
+
response.put("recordCount", allRecords.size());
|
| 38 |
+
|
| 39 |
+
// Test 4: Delete operation
|
| 40 |
+
testConnectionRepository.deleteById(saved.getId());
|
| 41 |
+
response.put("deleteOperation", "PASS");
|
| 42 |
+
|
| 43 |
+
response.put("overallStatus", "SUCCESS");
|
| 44 |
+
response.put("message", "All database operations completed successfully");
|
| 45 |
+
|
| 46 |
+
return ResponseEntity.ok(response);
|
| 47 |
+
} catch (Exception e) {
|
| 48 |
+
response.put("overallStatus", "FAILED");
|
| 49 |
+
response.put("error", e.getMessage());
|
| 50 |
+
response.put("errorClass", e.getClass().getSimpleName());
|
| 51 |
+
return ResponseEntity.status(500).body(response);
|
| 52 |
+
}
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
@PostMapping("/insert-test-data")
|
| 56 |
+
public ResponseEntity<TestConnection> insertTestData(@RequestParam(defaultValue = "Test message") String message) {
|
| 57 |
+
try {
|
| 58 |
+
TestConnection testEntity = new TestConnection(message);
|
| 59 |
+
TestConnection saved = testConnectionRepository.save(testEntity);
|
| 60 |
+
return ResponseEntity.ok(saved);
|
| 61 |
+
} catch (Exception e) {
|
| 62 |
+
return ResponseEntity.status(500).build();
|
| 63 |
+
}
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
@GetMapping("/all-test-data")
|
| 67 |
+
public ResponseEntity<List<TestConnection>> getAllTestData() {
|
| 68 |
+
try {
|
| 69 |
+
List<TestConnection> allRecords = testConnectionRepository.findAll();
|
| 70 |
+
return ResponseEntity.ok(allRecords);
|
| 71 |
+
} catch (Exception e) {
|
| 72 |
+
return ResponseEntity.status(500).build();
|
| 73 |
+
}
|
| 74 |
+
}
|
| 75 |
+
}
|
src/main/java/com/cs102/attendance/entity/TestConnection.java
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.cs102.attendance.entity;
|
| 2 |
+
|
| 3 |
+
import jakarta.persistence.*;
|
| 4 |
+
import java.time.LocalDateTime;
|
| 5 |
+
|
| 6 |
+
@Entity
|
| 7 |
+
@Table(name = "test_connections")
|
| 8 |
+
public class TestConnection {
|
| 9 |
+
|
| 10 |
+
@Id
|
| 11 |
+
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
| 12 |
+
private Long id;
|
| 13 |
+
|
| 14 |
+
@Column(name = "test_message")
|
| 15 |
+
private String testMessage;
|
| 16 |
+
|
| 17 |
+
@Column(name = "created_at")
|
| 18 |
+
private LocalDateTime createdAt;
|
| 19 |
+
|
| 20 |
+
public TestConnection() {
|
| 21 |
+
this.createdAt = LocalDateTime.now();
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
public TestConnection(String testMessage) {
|
| 25 |
+
this.testMessage = testMessage;
|
| 26 |
+
this.createdAt = LocalDateTime.now();
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
// Getters and setters
|
| 30 |
+
public Long getId() {
|
| 31 |
+
return id;
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
public void setId(Long id) {
|
| 35 |
+
this.id = id;
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
public String getTestMessage() {
|
| 39 |
+
return testMessage;
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
public void setTestMessage(String testMessage) {
|
| 43 |
+
this.testMessage = testMessage;
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
public LocalDateTime getCreatedAt() {
|
| 47 |
+
return createdAt;
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
public void setCreatedAt(LocalDateTime createdAt) {
|
| 51 |
+
this.createdAt = createdAt;
|
| 52 |
+
}
|
| 53 |
+
}
|
src/main/java/com/cs102/attendance/repository/TestConnectionRepository.java
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.cs102.attendance.repository;
|
| 2 |
+
|
| 3 |
+
import com.cs102.attendance.entity.TestConnection;
|
| 4 |
+
import org.springframework.data.jpa.repository.JpaRepository;
|
| 5 |
+
import org.springframework.data.jpa.repository.Query;
|
| 6 |
+
import org.springframework.stereotype.Repository;
|
| 7 |
+
|
| 8 |
+
@Repository
|
| 9 |
+
public interface TestConnectionRepository extends JpaRepository<TestConnection, Long> {
|
| 10 |
+
|
| 11 |
+
@Query(value = "SELECT 1", nativeQuery = true)
|
| 12 |
+
Integer testQuery();
|
| 13 |
+
}
|
src/main/resources/application.yml
CHANGED
|
@@ -7,6 +7,10 @@ spring:
|
|
| 7 |
username: ${SPRING_DATASOURCE_USERNAME}
|
| 8 |
password: ${SPRING_DATASOURCE_PASSWORD}
|
| 9 |
driver-class-name: org.postgresql.Driver
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
jpa:
|
| 11 |
hibernate:
|
| 12 |
ddl-auto: update
|
|
@@ -14,16 +18,17 @@ spring:
|
|
| 14 |
properties:
|
| 15 |
hibernate:
|
| 16 |
dialect: org.hibernate.dialect.PostgreSQLDialect
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
web:
|
| 21 |
-
exposure:
|
| 22 |
-
include: health,info,metrics,prometheus
|
| 23 |
|
|
|
|
| 24 |
recognition:
|
| 25 |
confidence: 0.6
|
| 26 |
cooldownMs: 10000
|
| 27 |
-
|
| 28 |
face-service:
|
| 29 |
-
url: http://localhost:5001
|
|
|
|
| 7 |
username: ${SPRING_DATASOURCE_USERNAME}
|
| 8 |
password: ${SPRING_DATASOURCE_PASSWORD}
|
| 9 |
driver-class-name: org.postgresql.Driver
|
| 10 |
+
hikari:
|
| 11 |
+
maximum-pool-size: 10
|
| 12 |
+
connection-timeout: 30000
|
| 13 |
+
idle-timeout: 600000
|
| 14 |
jpa:
|
| 15 |
hibernate:
|
| 16 |
ddl-auto: update
|
|
|
|
| 18 |
properties:
|
| 19 |
hibernate:
|
| 20 |
dialect: org.hibernate.dialect.PostgreSQLDialect
|
| 21 |
+
# security:
|
| 22 |
+
# user:
|
| 23 |
+
# name: ${SPRING_SECURITY_USER_NAME}
|
| 24 |
+
# password: ${SPRING_SECURITY_USER_PASSWORD}
|
| 25 |
|
| 26 |
+
# Expose metrics for demo proof
|
| 27 |
+
management.endpoints.web.exposure.include: health,info,metrics,prometheus
|
|
|
|
|
|
|
|
|
|
| 28 |
|
| 29 |
+
# Externalised CV thresholds
|
| 30 |
recognition:
|
| 31 |
confidence: 0.6
|
| 32 |
cooldownMs: 10000
|
|
|
|
| 33 |
face-service:
|
| 34 |
+
url: http://localhost:5001 # backend face service url
|
src/test/java/com/cs102/attendance/Cs102AttendanceProjectApplicationTests.java
CHANGED
|
@@ -1,13 +1,50 @@
|
|
| 1 |
package com.cs102.attendance;
|
| 2 |
|
|
|
|
| 3 |
import org.junit.jupiter.api.Test;
|
|
|
|
| 4 |
import org.springframework.boot.test.context.SpringBootTest;
|
| 5 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
@SpringBootTest
|
| 7 |
class Cs102AttendanceProjectApplicationTests {
|
| 8 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
@Test
|
| 10 |
void contextLoads() {
|
| 11 |
}
|
| 12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
}
|
|
|
|
| 1 |
package com.cs102.attendance;
|
| 2 |
|
| 3 |
+
import com.cs102.attendance.repository.TestConnectionRepository;
|
| 4 |
import org.junit.jupiter.api.Test;
|
| 5 |
+
import org.springframework.beans.factory.annotation.Autowired;
|
| 6 |
import org.springframework.boot.test.context.SpringBootTest;
|
| 7 |
|
| 8 |
+
import javax.sql.DataSource;
|
| 9 |
+
import java.sql.Connection;
|
| 10 |
+
import java.sql.SQLException;
|
| 11 |
+
|
| 12 |
+
import static org.junit.jupiter.api.Assertions.*;
|
| 13 |
+
|
| 14 |
@SpringBootTest
|
| 15 |
class Cs102AttendanceProjectApplicationTests {
|
| 16 |
|
| 17 |
+
@Autowired
|
| 18 |
+
private DataSource dataSource;
|
| 19 |
+
|
| 20 |
+
@Autowired
|
| 21 |
+
private TestConnectionRepository testConnectionRepository;
|
| 22 |
+
|
| 23 |
@Test
|
| 24 |
void contextLoads() {
|
| 25 |
}
|
| 26 |
|
| 27 |
+
@Test
|
| 28 |
+
void testDatabaseConnection() throws SQLException {
|
| 29 |
+
// Test that we can get a connection from the DataSource
|
| 30 |
+
try (Connection connection = dataSource.getConnection()) {
|
| 31 |
+
assertNotNull(connection, "Database connection should not be null");
|
| 32 |
+
assertTrue(connection.isValid(5), "Database connection should be valid");
|
| 33 |
+
|
| 34 |
+
// Print connection details for verification
|
| 35 |
+
System.out.println("Database URL: " + connection.getMetaData().getURL());
|
| 36 |
+
System.out.println("Database Driver: " + connection.getMetaData().getDriverName());
|
| 37 |
+
System.out.println("Database Version: " + connection.getMetaData().getDatabaseProductVersion());
|
| 38 |
+
}
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
@Test
|
| 42 |
+
void testRepositoryConnection() {
|
| 43 |
+
// Test that the repository can execute queries
|
| 44 |
+
assertDoesNotThrow(() -> {
|
| 45 |
+
Integer result = testConnectionRepository.testQuery();
|
| 46 |
+
assertEquals(1, result, "Test query should return 1");
|
| 47 |
+
}, "Repository test query should not throw an exception");
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
}
|
src/test/java/com/cs102/attendance/controller/TestControllerTest.java
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.cs102.attendance.controller;
|
| 2 |
+
|
| 3 |
+
import com.cs102.attendance.entity.TestConnection;
|
| 4 |
+
import com.cs102.attendance.repository.TestConnectionRepository;
|
| 5 |
+
import com.fasterxml.jackson.databind.ObjectMapper;
|
| 6 |
+
import org.junit.jupiter.api.Test;
|
| 7 |
+
import org.springframework.beans.factory.annotation.Autowired;
|
| 8 |
+
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
| 9 |
+
import org.springframework.boot.test.mock.mockito.MockBean;
|
| 10 |
+
import org.springframework.http.MediaType;
|
| 11 |
+
import org.springframework.test.web.servlet.MockMvc;
|
| 12 |
+
|
| 13 |
+
import static org.mockito.ArgumentMatchers.any;
|
| 14 |
+
import static org.mockito.Mockito.when;
|
| 15 |
+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
| 16 |
+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
| 17 |
+
|
| 18 |
+
@WebMvcTest(TestController.class)
|
| 19 |
+
public class TestControllerTest {
|
| 20 |
+
|
| 21 |
+
@Autowired
|
| 22 |
+
private MockMvc mockMvc;
|
| 23 |
+
|
| 24 |
+
@MockBean
|
| 25 |
+
private TestConnectionRepository testConnectionRepository;
|
| 26 |
+
|
| 27 |
+
@Autowired
|
| 28 |
+
private ObjectMapper objectMapper;
|
| 29 |
+
|
| 30 |
+
@Test
|
| 31 |
+
public void testInsertTestDataWithDefaultMessage() throws Exception {
|
| 32 |
+
// Given
|
| 33 |
+
TestConnection mockSavedEntity = new TestConnection("Test message");
|
| 34 |
+
mockSavedEntity.setId(1L);
|
| 35 |
+
when(testConnectionRepository.save(any(TestConnection.class))).thenReturn(mockSavedEntity);
|
| 36 |
+
|
| 37 |
+
// When & Then
|
| 38 |
+
mockMvc.perform(post("/api/test/insert-test-data")
|
| 39 |
+
.contentType(MediaType.APPLICATION_JSON))
|
| 40 |
+
.andExpect(status().isOk())
|
| 41 |
+
.andExpect(jsonPath("$.id").value(1L))
|
| 42 |
+
.andExpect(jsonPath("$.message").value("Test message"));
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
@Test
|
| 46 |
+
public void testInsertTestDataWithCustomMessage() throws Exception {
|
| 47 |
+
// Given
|
| 48 |
+
String customMessage = "Custom test message";
|
| 49 |
+
TestConnection mockSavedEntity = new TestConnection(customMessage);
|
| 50 |
+
mockSavedEntity.setId(2L);
|
| 51 |
+
when(testConnectionRepository.save(any(TestConnection.class))).thenReturn(mockSavedEntity);
|
| 52 |
+
|
| 53 |
+
// When & Then
|
| 54 |
+
mockMvc.perform(post("/api/test/insert-test-data")
|
| 55 |
+
.param("message", customMessage)
|
| 56 |
+
.contentType(MediaType.APPLICATION_JSON))
|
| 57 |
+
.andExpect(status().isOk())
|
| 58 |
+
.andExpect(jsonPath("$.id").value(2L))
|
| 59 |
+
.andExpect(jsonPath("$.message").value(customMessage));
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
@Test
|
| 63 |
+
public void testInsertTestDataWithException() throws Exception {
|
| 64 |
+
// Given
|
| 65 |
+
when(testConnectionRepository.save(any(TestConnection.class)))
|
| 66 |
+
.thenThrow(new RuntimeException("Database error"));
|
| 67 |
+
|
| 68 |
+
// When & Then
|
| 69 |
+
mockMvc.perform(post("/api/test/insert-test-data")
|
| 70 |
+
.contentType(MediaType.APPLICATION_JSON))
|
| 71 |
+
.andExpect(status().isInternalServerError());
|
| 72 |
+
}
|
| 73 |
+
}
|