-
Notifications
You must be signed in to change notification settings - Fork 135
Improve tests #131
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Comments
maige could you help with that? |
@coderabbitai find Spring Boot test classes in the code and improve those tests |
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed:
Length of output: 557 🏁 Script executed:
Length of output: 2892 🏁 Script executed:
Length of output: 8499 🏁 Script executed:
Length of output: 2242 🏁 Script executed:
Length of output: 6907 flowchart TB
A(["Improve Spring Boot Tests"])
A --o B["1. Enhance Repository Tests"]
A --o C["2. Add Controller Tests"]
A --o D["3. Add Integration Tests"]
B --o B1["Add edge cases & validation tests"]
B --o B2["Add update/delete operation tests"]
B --o B3["Improve assertions & test structure"]
C --o C1["Create AccountController tests"]
C --o C2["Complete CustomerController tests"]
C --o C3["Create ProductController tests"]
D --o D1["Test service-to-service communication"]
D --o D2["Add proper mocking & error handling"]
D --o D3["Test failure scenarios"]
@piomin I've analyzed the current test files in your codebase and have a plan to improve them. Here's what I found:
I've created a comprehensive plan for improving the tests, which includes:
Another agent will come along to implement these changes. Would you like me to prioritize any specific area of testing first? ⏳ Preparing changes... |
Caution CodeRabbit did not find changes to make. |
@coderabbitai can you prepare a new PR with changes according to your comprehensive plan for improving the tests? |
Tip For best results, initiate chat on the files or code changes. A summary of the edits CodeRabbit can apply:
A plan of each step that CodeRabbit will take in order to execute the edits for each file (with inline rough draft snippets): ✏️ account-service/src/test/java/pl/piomin/microservices/advanced/account/repository/AccountRepositoryTest.javaAfter the existing imports, insert new imports for List, UUID, and the additional assertion methods. For example, immediately after the line import static org.junit.jupiter.api.Assertions.assertEquals;
In
In
Account a = repository.findByNumber(ACCOUNT_NUMBER);
Add
Add
Then after the static imports (around line 22), insert: import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse; Define constants for the test data. Immediately after static final String CUSTOMER_NAME = "Test1";
static final String CUSTOMER_PESEL = "1234567890"; Update the existing c.setName("Test1");
c.setPesel("1234567890"); to c.setName(CUSTOMER_NAME);
c.setPesel(CUSTOMER_PESEL); and after saving add: assertEquals(CUSTOMER_NAME, c.getName());
assertEquals(CUSTOMER_PESEL, c.getPesel());
assertEquals(CustomerType.INDIVIDUAL, c.getType()); Enhance the Customer customer = optCus.get();
assertEquals(id, customer.getId());
assertEquals(CUSTOMER_NAME, customer.getName());
assertEquals(CUSTOMER_PESEL, customer.getPesel());
assertEquals(CustomerType.INDIVIDUAL, customer.getType()); And in assertEquals(id, c.getId());
assertEquals(CUSTOMER_NAME, c.getName());
assertEquals(CustomerType.INDIVIDUAL, c.getType()); Add the following new test methods before the closing brace of the class (after line 68): @Test
@Order(3)
public void testUpdateCustomer() {
Optional<Customer> optCus = repository.findById(id);
assertTrue(optCus.isPresent());
Customer customer = optCus.get();
// Update name
String newName = "Updated Name";
customer.setName(newName);
Customer updated = repository.save(customer);
assertEquals(newName, updated.getName());
assertEquals(id, updated.getId());
assertEquals(CUSTOMER_PESEL, updated.getPesel());
assertEquals(CustomerType.INDIVIDUAL, updated.getType());
}
@Test
@Order(4)
public void testFindAllCustomers() {
List<Customer> customers = repository.findAll();
assertNotNull(customers);
assertFalse(customers.isEmpty());
assertTrue(customers.size() >= 1);
}
@Test
@Order(5)
public void testAddCorporateCustomer() {
Customer c = new Customer();
c.setName("Corporate Inc.");
c.setPesel("9876543210");
c.setType(CustomerType.CORPORATE);
c = repository.save(c);
assertNotNull(c);
assertNotNull(c.getId());
assertEquals("Corporate Inc.", c.getName());
assertEquals("9876543210", c.getPesel());
assertEquals(CustomerType.CORPORATE, c.getType());
}
@Test
@Order(6)
public void testFindNonExistentCustomer() {
String randomId = UUID.randomUUID().toString();
Optional<Customer> optCustomer = repository.findById(randomId);
assertFalse(optCustomer.isPresent());
Customer nonExistentCustomer = repository.findByPesel("non-existent-pesel");
assertEquals(null, nonExistentCustomer);
} Run the updated test suite to verify that all tests compile and pass against the Testcontainer-backed MongoDB instance. ✏️ product-service/src/test/java/pl/piomin/microservices/advanced/product/ProductRepositoryTests.javaAfter existing imports add: import java.util.List;
import java.util.UUID; After static final String ACCOUNT_ID = "123";
static final String CUSTOMER_ID = "123";
static final int INITIAL_BALANCE = 10000; In - p.setAccountId("123");
- p.setCustomerId("123");
+ p.setAccountId(ACCOUNT_ID);
+ p.setCustomerId(CUSTOMER_ID);
p.setType(ProductType.CREDIT);
- p.setBalance(10000);
+ p.setBalance(INITIAL_BALANCE);
p.setDateOfStart(LocalDate.now());
p = repository.save(p);
assertNotNull(p);
assertNotNull(p.getId());
+ assertEquals(ACCOUNT_ID, p.getAccountId());
+ assertEquals(CUSTOMER_ID, p.getCustomerId());
+ assertEquals(ProductType.CREDIT, p.getType());
+ assertEquals(INITIAL_BALANCE, p.getBalance());
+ assertNotNull(p.getDateOfStart());
id = p.getId(); In Product product = optCus.get();
assertEquals(id, product.getId());
assertEquals(ACCOUNT_ID, product.getAccountId());
assertEquals(CUSTOMER_ID, product.getCustomerId());
assertEquals(ProductType.CREDIT, product.getType());
assertEquals(INITIAL_BALANCE, product.getBalance()); In - Product p = repository.findByAccountId("123");
+ Product p = repository.findByAccountId(ACCOUNT_ID);
assertNotNull(p);
assertNotNull(p.getId());
+ assertEquals(id, p.getId());
+ assertEquals(CUSTOMER_ID, p.getCustomerId());
+ assertEquals(ProductType.CREDIT, p.getType());
+ assertEquals(INITIAL_BALANCE, p.getBalance()); Append these new test methods after the existing ones: @Test
@Order(3)
public void testUpdateProductBalance() {
Product product = repository.findById(id).get();
int newBalance = 15000;
product.setBalance(newBalance);
Product updated = repository.save(product);
assertEquals(newBalance, updated.getBalance());
assertEquals(id, updated.getId());
assertEquals(ACCOUNT_ID, updated.getAccountId());
assertEquals(ProductType.CREDIT, updated.getType());
}
@Test
@Order(4)
public void testFindAllProducts() {
List<Product> products = repository.findAll();
assertNotNull(products);
assertFalse(products.isEmpty());
assertTrue(products.size() >= 1);
}
@Test
@Order(5)
public void testAddDebitProduct() {
Product p = new Product();
p.setAccountId("456");
p.setCustomerId("456");
p.setType(ProductType.DEBIT);
p.setBalance(5000);
p.setDateOfStart(LocalDate.now());
p = repository.save(p);
assertNotNull(p);
assertNotNull(p.getId());
assertEquals("456", p.getAccountId());
assertEquals("456", p.getCustomerId());
assertEquals(ProductType.DEBIT, p.getType());
assertEquals(5000, p.getBalance());
}
@Test
@Order(6)
public void testFindNonExistentProduct() {
String randomId = UUID.randomUUID().toString();
Optional<Product> optProduct = repository.findById(randomId);
assertFalse(optProduct.isPresent());
Product nonExistentProduct = repository.findByAccountId("non-existent-account");
assertNull(nonExistentProduct);
} ✏️ customer-service/src/test/java/pl/piomin/microservices/advanced/customer/CustomerControllerTests.javaAdd these imports after existing ones: import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import org.junit.jupiter.api.Test; After static String id;
static final String CUSTOMER_PESSEL = "1234567890";
static final String CUSTOMER_NAME = "Jan Testowy"; In - c = template.postForObject("/customers", c, Customer.class);
+ Customer created = template.postForObject("/customers", c, Customer.class);
+ assertNotNull(created);
+ assertNotNull(created.getId());
+ assertEquals(CUSTOMER_PESSEL, created.getPesel());
+ assertEquals(CUSTOMER_NAME, created.getName());
+ assertEquals(CustomerType.INDIVIDUAL, created.getType());
+ id = created.getId(); Uncomment and update the second test method to enable it: -// @Test
-// @Order(2)
-public void findCustomerWithAccounts(Hoverfly hoverfly) {
+ @Test
+ @Order(2)
+ public void findCustomerWithAccounts(Hoverfly hoverfly) {
hoverfly.simulate(
dsl(service("http://account-service")
.get(startsWith("/accounts/customer"))
.willReturn(success("[{\"id\":\"1\",\"number\":\"1234567890\"}]", "application/json"))));
- Customer c = template.getForObject("/customers/pesel/{pesel}", Customer.class, "1234567890");
- Customer cc = template.getForObject("/customers/{id}", Customer.class, c.getId());
+ Customer c = template.getForObject("/customers/pesel/{pesel}", Customer.class, CUSTOMER_PESSEL);
+ Customer cc = template.getForObject("/customers/{id}", Customer.class, id);
assertNotNull(cc);
assertTrue(cc.getAccounts().size() > 0);
} 📄 account-service/src/test/java/pl/piomin/microservices/advanced/account/api/AccountControllerTest.javaCreate a new file with the following content: package pl.piomin.microservices.advanced.account.api;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
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.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.MongoDBContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import pl.piomin.microservices.advanced.account.model.Account;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
properties = {"spring.cloud.discovery.enabled=false"})
@Testcontainers
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class AccountControllerTest {
@Container
static MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:8.0");
@DynamicPropertySource
static void registerMongoProperties(DynamicPropertyRegistry registry) {
registry.add("spring.data.mongodb.uri", () -> mongoDBContainer.getConnectionString() + "/test");
}
@Autowired
TestRestTemplate restTemplate;
private static String accountId;
private static final String ACCOUNT_NUMBER = "ACC12345678";
private static final String CUSTOMER_ID = "CUST12345";
@Test
@Order(1)
public void testAddAccount() {
Account account = new Account();
account.setNumber(ACCOUNT_NUMBER);
account.setCustomerId(CUSTOMER_ID);
account.setBalance(5000);
ResponseEntity<Account> response = restTemplate.postForEntity("/accounts", account, Account.class);
assertEquals(HttpStatus.OK, response.getStatusCode());
Account created = response.getBody();
assertNotNull(created);
assertNotNull(created.getId());
assertEquals(ACCOUNT_NUMBER, created.getNumber());
assertEquals(CUSTOMER_ID, created.getCustomerId());
assertEquals(5000, created.getBalance());
accountId = created.getId();
}
@Test
@Order(2)
public void testFindByNumber() {
ResponseEntity<Account> response = restTemplate.getForEntity("/accounts/{number}", Account.class, ACCOUNT_NUMBER);
assertEquals(HttpStatus.OK, response.getStatusCode());
Account found = response.getBody();
assertNotNull(found);
assertEquals(accountId, found.getId());
assertEquals(ACCOUNT_NUMBER, found.getNumber());
assertEquals(CUSTOMER_ID, found.getCustomerId());
}
@Test
@Order(3)
public void testFindByCustomer() {
ResponseEntity<List<Account>> response = restTemplate.exchange(
"/accounts/customer/{customerId}",
HttpMethod.GET,
null,
new ParameterizedTypeReference<List<Account>>() {},
CUSTOMER_ID);
assertEquals(HttpStatus.OK, response.getStatusCode());
List<Account> list = response.getBody();
assertNotNull(list);
assertFalse(list.isEmpty());
assertEquals(1, list.size());
assertEquals(accountId, list.get(0).getId());
assertEquals(ACCOUNT_NUMBER, list.get(0).getNumber());
}
@Test
@Order(4)
public void testFindAll() {
ResponseEntity<List<Account>> response = restTemplate.exchange(
"/accounts",
HttpMethod.GET,
null,
new ParameterizedTypeReference<List<Account>>() {});
assertEquals(HttpStatus.OK, response.getStatusCode());
assertNotNull(response.getBody());
assertFalse(response.getBody().isEmpty());
}
@Test
@Order(5)
public void testUpdateAccount() {
ResponseEntity<Account> getResp = restTemplate.getForEntity("/accounts/{number}", Account.class, ACCOUNT_NUMBER);
Account account = getResp.getBody();
assertNotNull(account);
int newBalance = 7500;
account.setBalance(newBalance);
restTemplate.put("/accounts", account);
ResponseEntity<Account> updatedResp = restTemplate.getForEntity("/accounts/{number}", Account.class, ACCOUNT_NUMBER);
assertEquals(newBalance, updatedResp.getBody().getBalance());
assertEquals(accountId, updatedResp.getBody().getId());
}
} 📄 product-service/src/test/java/pl/piomin/microservices/advanced/product/api/ProductControllerTest.javaCreate a new file with the following content: package pl.piomin.microservices.advanced.product.api;
import io.specto.hoverfly.junit.core.Hoverfly;
import io.specto.hoverfly.junit.core.config.LogLevel;
import io.specto.hoverfly.junit5.HoverflyExtension;
import io.specto.hoverfly.junit5.api.HoverflyConfig;
import io.specto.hoverfly.junit5.api.HoverflyCore;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.extension.ExtendWith;
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.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.MongoDBContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import pl.piomin.microservices.advanced.product.model.Product;
import pl.piomin.microservices.advanced.product.model.ProductType;
import java.time.LocalDate;
import java.util.List;
import static io.specto.hoverfly.junit.core.SimulationSource.dsl;
import static io.specto.hoverfly.junit.dsl.HoverflyDsl.service;
import static io.specto.hoverfly.junit.dsl.ResponseCreators.success;
import static io.specto.hoverfly.junit.dsl.matchers.HoverflyMatchers.startsWith;
import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
properties = {"spring.cloud.discovery.enabled=false"})
@Testcontainers
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@HoverflyCore(config = @HoverflyConfig(logLevel = LogLevel.DEBUG))
@ExtendWith(HoverflyExtension.class)
public class ProductControllerTest {
@Container
static MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:8.0");
@DynamicPropertySource
static void registerMongoProperties(DynamicPropertyRegistry registry) {
registry.add("spring.data.mongodb.uri", () -> mongoDBContainer.getConnectionString() + "/test");
}
@Autowired
TestRestTemplate template;
private static String productId;
private static final String ACCOUNT_ID = "ACC987654";
private static final String CUSTOMER_ID = "CUST987654";
private static final int INITIAL_BALANCE = 10000;
@Test
@Order(1)
public void testAddProduct() {
Product product = new Product();
product.setAccountId(ACCOUNT_ID);
product.setCustomerId(CUSTOMER_ID);
product.setType(ProductType.CREDIT);
product.setBalance(INITIAL_BALANCE);
product.setDateOfStart(LocalDate.now());
ResponseEntity<Product> response = template.postForEntity("/products", product, Product.class);
assertEquals(HttpStatus.OK, response.getStatusCode());
Product created = response.getBody();
assertNotNull(created);
assertNotNull(created.getId());
assertEquals(ACCOUNT_ID, created.getAccountId());
assertEquals(CUSTOMER_ID, created.getCustomerId());
assertEquals(ProductType.CREDIT, created.getType());
assertEquals(INITIAL_BALANCE, created.getBalance());
assertNotNull(created.getDateOfStart());
productId = created.getId();
}
@Test
@Order(2)
public void testFindByAccountId() {
ResponseEntity<Product> response = template.getForEntity("/products/account/{accountId}", Product.class, ACCOUNT_ID);
assertEquals(HttpStatus.OK, response.getStatusCode());
Product found = response.getBody();
assertNotNull(found);
assertEquals(productId, found.getId());
assertEquals(ACCOUNT_ID, found.getAccountId());
assertEquals(CUSTOMER_ID, found.getCustomerId());
assertEquals(ProductType.CREDIT, found.getType());
}
@Test
@Order(3)
public void testFindById(Hoverfly hoverfly) {
hoverfly.simulate(
dsl(service("http://account-service")
.get(startsWith("/accounts/" + productId))
.willReturn(success("{\"id\":\"" + productId + "\",\"customerId\":\"" + CUSTOMER_ID + "\"}", "application/json"))));
ResponseEntity<Product> response = template.getForEntity("/products/{id}", Product.class, productId);
assertEquals(HttpStatus.OK, response.getStatusCode());
Product found = response.getBody();
assertNotNull(found);
assertEquals(productId, found.getId());
assertEquals(ACCOUNT_ID, found.getAccountId());
assertEquals(CUSTOMER_ID, found.getCustomerId());
}
@Test
@Order(4)
public void testFindAll() {
ResponseEntity<List<Product>> response = template.exchange(
"/products", HttpMethod.GET, null, new ParameterizedTypeReference<List<Product>>() {});
assertEquals(HttpStatus.OK, response.getStatusCode());
assertNotNull(response.getBody());
assertFalse(response.getBody().isEmpty());
}
@Test
@Order(5)
public void testFindByNonExistentAccountId() {
ResponseEntity<Product> response = template.getForEntity(
"/products/account/{accountId}", Product.class, "non-existent-account");
assertEquals(HttpStatus.OK, response.getStatusCode());
assertNull(response.getBody());
}
} 📄 account-service/src/test/java/pl/piomin/microservices/advanced/account/config/AccountContainersConfiguration.javaCreate this TestConfiguration class: package pl.piomin.microservices.advanced.account.config;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.MongoDBContainer;
import org.testcontainers.junit.jupiter.Container;
@TestConfiguration
public class AccountContainersConfiguration {
@Container
private static final MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:8.0");
static {
mongoDBContainer.start();
}
@DynamicPropertySource
static void setProperties(DynamicPropertyRegistry registry) {
String uri = mongoDBContainer.getConnectionString() + "/test";
registry.add("spring.data.mongodb.uri", () -> uri);
}
@Bean
public MongoDBContainer mongoDbContainer() {
return mongoDBContainer;
}
} 📄 customer-service/src/test/java/pl/piomin/microservices/advanced/customer/config/CustomerContainersConfiguration.javaCreate this TestConfiguration class: package pl.piomin.microservices.advanced.customer.config;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.MongoDBContainer;
import org.testcontainers.junit.jupiter.Container;
@TestConfiguration
public class CustomerContainersConfiguration {
@Container
private static final MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:8.0");
static {
mongoDBContainer.start();
}
@DynamicPropertySource
static void setProperties(DynamicPropertyRegistry registry) {
String uri = mongoDBContainer.getConnectionString() + "/test";
registry.add("spring.data.mongodb.uri", () -> uri);
}
@Bean
public MongoDBContainer mongoDbContainer() {
return mongoDBContainer;
}
} 📄 product-service/src/test/java/pl/piomin/microservices/advanced/product/config/ProductContainersConfiguration.javaCreate this TestConfiguration class: package pl.piomin.microservices.advanced.product.config;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.MongoDBContainer;
import org.testcontainers.junit.jupiter.Container;
@TestConfiguration
public class ProductContainersConfiguration {
@Container
private static final MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:8.0");
static {
mongoDBContainer.start();
}
@DynamicPropertySource
static void setProperties(DynamicPropertyRegistry registry) {
String uri = mongoDBContainer.getConnectionString() + "/test";
registry.add("spring.data.mongodb.uri", () -> uri);
}
@Bean
public MongoDBContainer mongoDbContainer() {
return mongoDBContainer;
}
} 📄 integration-tests/src/test/java/pl/piomin/microservices/advanced/integration/ServiceIntegrationTests.javaCreate a new test class annotated with:
A summary of the context that CodeRabbit is considering across the codebase:
|
Creating a PR to execute the edits.... The changes have been created in this pull request: View PR |
Maige find Spring Boot test classes in the code and improve those tests
The text was updated successfully, but these errors were encountered: