Commit 3f498866 authored by Ashok Kumar K's avatar Ashok Kumar K

unit tests to web layer and integration tests

parent 1e10cd9f
......@@ -8,8 +8,8 @@ import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.Errors;
......@@ -24,7 +24,7 @@ import static org.springframework.web.reactive.function.server.ServerResponse.cr
import static org.springframework.web.reactive.function.server.ServerResponse.ok;
@Slf4j
@Component
@Configuration
public class ProductHandler {
@Autowired
......@@ -57,7 +57,6 @@ public class ProductHandler {
.flatMap(product -> productService.updateProduct(req.pathVariable(SKU_TEXT), product))
.flatMap(product -> accepted()
.bodyValue(product))
)
.DELETE(SKU_TEXT_PATH_VAR,
req -> productService.removeProduct(req.pathVariable(SKU_TEXT))
......
......@@ -17,7 +17,7 @@ import static org.springframework.http.HttpStatus.NOT_FOUND;
@Component
@Slf4j
public class ApiError extends DefaultErrorAttributes {
public class ApiErrorAttributes extends DefaultErrorAttributes {
@Override
public Map<String, Object> getErrorAttributes(ServerRequest request, ErrorAttributeOptions options) {
......
......@@ -14,4 +14,6 @@ public interface ProductRepository {
Mono<Product> updateProduct(String sku, Product product);
Mono<Long> removeProduct(String sku);
Mono<Long> removeAllProducts();
}
......@@ -54,4 +54,9 @@ public class ProductRepositoryImpl implements ProductRepository {
.map(DeleteResult::getDeletedCount);
}
@Override
public Mono<Long> removeAllProducts() {
return template.remove(new Query(), Product.class)
.map(DeleteResult::getDeletedCount);
}
}
spring:
data:
mongodb:
host: localhost
port: 27017
database: reactive-test
\ No newline at end of file
package com.nisum.reactiveweb;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class ReactiveWebApplicationTests {
@Test
void contextLoads() {
}
}
package com.nisum.reactiveweb.controller;
import com.nisum.reactiveweb.exceptions.ApiErrorAttributes;
import com.nisum.reactiveweb.exceptions.ProductNotFoundException;
import com.nisum.reactiveweb.model.Product;
import com.nisum.reactiveweb.service.ProductServiceImpl;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.math.BigDecimal;
import java.util.function.Predicate;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import org.springframework.test.web.reactive.server.WebTestClient;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.when;
import static reactor.core.publisher.Mono.just;
@WebFluxTest()
@Import({ProductHandler.class, ApiErrorAttributes.class})
class ProductHandlerComponentTests {
@Autowired
private WebTestClient testClient;
@MockBean
private ProductServiceImpl productService;
private final Product product1 = new Product("1", "toy", new BigDecimal(200));
private final Product product3 = new Product("1", "toy", new BigDecimal(300));
private final Product product2 = new Product("2", "table", new BigDecimal(400));
private final Predicate<Product> productPredicate1 = productPredicate("1", "toy", 200);
private final Predicate<Product> productPredicate2 = productPredicate("1", "toy", 300);
private final Mono<Product> productNotFoundErrorMono = Mono.error(ProductNotFoundException::new);
@Test
void getProductBySku() {
when(productService.getProductBySku("1")).thenReturn(productMono());
testClient.get()
.uri("/product/1")
.exchange()
.expectStatus().isOk()
.expectBody(Product.class).value(Matchers.equalTo(product1));
}
@Test
void getProductBySkuWhenProductDoesNotExist() {
when(productService.getProductBySku("1")).thenReturn(productNotFoundErrorMono);
testClient.get()
.uri("/product/1")
.exchange()
.expectStatus().isNotFound();
}
@Test
void saveProduct() {
Product productToSave = new Product(null, "toy", new BigDecimal(200));
when(productService.saveProduct(productToSave)).thenReturn(productMono());
testClient.post()
.uri("/product")
.body(just(productToSave), Product.class)
.exchange()
.expectStatus().isCreated()
.expectBody(Product.class).isEqualTo(product1)
.consumeWith(result -> {
Product savedProduct = result.getResponseBody();
assertNotNull(savedProduct);
assertNotNull(savedProduct.getSku());
assertTrue(productPredicate1.test(savedProduct));
});
}
@Test
void saveProductWithProductNameOrPriceAsNull() {
Product productToSave = new Product();
testClient.post()
.uri("/product")
.body(just(productToSave), Product.class)
.exchange()
.expectStatus().isBadRequest();
}
@Test
void updateProduct() {
Product productToUpdate = new Product(null, "toy", new BigDecimal(300));
String sku = "1";
when(productService.updateProduct(sku, productToUpdate)).thenReturn(Mono.just(product3));
testClient.put()
.uri("/product/" + sku)
.body(just(productToUpdate), Product.class)
.exchange()
.expectStatus().isAccepted()
.expectBody(Product.class).isEqualTo(product3)
.consumeWith(result -> {
Product updatedProduct = result.getResponseBody();
assertNotNull(updatedProduct);
assertEquals(sku, updatedProduct.getSku());
assertEquals(product3.getPrice(), updatedProduct.getPrice());
assertTrue(productPredicate2.test(updatedProduct));
});
}
@Test
void updateProductWhenProductNameOrPriceIsNull() {
Product productToUpdate = new Product();
String sku = "5";
testClient.put()
.uri("/product/" + sku)
.body(just(productToUpdate), Product.class)
.exchange()
.expectStatus().isBadRequest();
}
@Test
void updateProductWhenProductDoesNotExistWithGivenSku() {
Product productToUpdate = new Product(null, "toy", new BigDecimal(300));
String sku = "5";
when(productService.updateProduct(sku, productToUpdate)).thenReturn(productNotFoundErrorMono);
testClient.put()
.uri("/product/" + sku)
.body(just(productToUpdate), Product.class)
.exchange()
.expectStatus().isNotFound();
}
@Test
void removeProduct() {
String sku = "5";
final String deletedText = "deleted";
when(productService.removeProduct(sku)).thenReturn(Mono.just(deletedText));
testClient.delete()
.uri("/product/" + sku)
.exchange()
.expectStatus().isOk()
.expectBody(String.class)
.consumeWith(result -> assertEquals(deletedText, result.getResponseBody()));
}
@Test
void removeProductWhenSkuDoesNotExist() {
String sku = "5";
when(productService.removeProduct(sku)).thenReturn(Mono.error(ProductNotFoundException::new));
testClient.delete()
.uri("/product/" + sku)
.exchange()
.expectStatus().isNotFound();
}
@Test
void getAllProducts() {
when(productService.getAllProducts()).thenReturn(productsFlux());
testClient.get().uri("/products")
.exchange()
.expectStatus().isOk()
.expectBodyList(Product.class)
.hasSize(2)
.contains(product1, product2);
}
private Mono<Product> productMono() {
return just(product1);
}
private Flux<Product> productsFlux() {
return Flux.just(product1, product2);
}
private Predicate<Product> productPredicate(String sku, String name, int price) {
return product -> product.getSku().equals(sku)
&& product.getName().equals(name)
&& product.getPrice().intValue() == price;
}
}
\ No newline at end of file
package com.nisum.reactiveweb.controller;
import com.nisum.reactiveweb.model.Product;
import com.nisum.reactiveweb.repository.ProductRepository;
import java.math.BigDecimal;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestMethodOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.reactive.server.WebTestClient;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static reactor.core.publisher.Mono.just;
@SpringBootTest
@ActiveProfiles("test")
@TestMethodOrder(OrderAnnotation.class)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@AutoConfigureWebTestClient
class ProductHandlerIntegrationTests {
@Autowired
private WebTestClient testClient;
@Autowired
private ProductRepository repository;
private String sku = "";
@BeforeAll
@AfterAll
void setup() {
repository.removeAllProducts().block();
}
@Test
@Order(3)
void getProductBySku() {
testClient.get()
.uri("/product/" + sku)
.exchange()
.expectStatus().isOk()
.expectBody(Product.class)
.consumeWith(result -> {
Product product = result.getResponseBody();
assertNotNull(product);
});
}
@Test
void getProductBySkuWhenProductDoesNotExist() {
testClient.get()
.uri("/product/1")
.exchange()
.expectStatus().isNotFound();
}
@Test
@Order(1)
void saveProduct() {
Product productToSave = new Product(null, "toy", new BigDecimal(200));
testClient.post()
.uri("/product")
.body(just(productToSave), Product.class)
.exchange()
.expectStatus().isCreated()
.expectBody(Product.class)
.consumeWith(result -> {
Product savedProduct = result.getResponseBody();
assertNotNull(savedProduct);
assertNotNull(savedProduct.getSku());
sku = savedProduct.getSku();
assertEquals(productToSave.getName(), savedProduct.getName());
assertEquals(productToSave.getPrice(), savedProduct.getPrice());
});
}
@Test
void saveProductWithProductNameOrPriceAsNull() {
Product productToSave = new Product();
testClient.post()
.uri("/product")
.body(just(productToSave), Product.class)
.exchange()
.expectStatus().isBadRequest();
}
@Test
@Order(2)
void updateProduct() {
String productName = "toy";
BigDecimal productPrice = new BigDecimal(300);
Product productToUpdate = new Product(null, productName, productPrice);
testClient.put()
.uri("/product/" + sku)
.body(just(productToUpdate), Product.class)
.exchange()
.expectStatus().isAccepted()
.expectBody(Product.class)
.consumeWith(result -> {
Product updatedProduct = result.getResponseBody();
assertNotNull(updatedProduct);
assertEquals(sku, updatedProduct.getSku());
assertEquals(productName, updatedProduct.getName());
assertEquals(productPrice, updatedProduct.getPrice());
});
}
@Test
void updateProductWhenProductNameOrPriceIsNull() {
Product productToUpdate = new Product();
testClient.put()
.uri("/product/" + sku)
.body(just(productToUpdate), Product.class)
.exchange()
.expectStatus().isBadRequest();
}
@Test
void updateProductWhenProductDoesNotExistWithGivenSku() {
Product productToUpdate = new Product(null, "toy", new BigDecimal(300));
String sku = "5";
testClient.put()
.uri("/product/" + sku)
.body(just(productToUpdate), Product.class)
.exchange()
.expectStatus().isNotFound();
}
@Test
@Order(10)
void removeProduct() {
final String deletedText = "deleted";
testClient.delete()
.uri("/product/" + sku)
.exchange()
.expectStatus().isOk()
.expectBody(String.class)
.consumeWith(result -> assertEquals(deletedText, result.getResponseBody()));
}
@Test
void removeProductWhenSkuDoesNotExist() {
String sku = "5";
testClient.delete()
.uri("/product/" + sku)
.exchange()
.expectStatus().isNotFound();
}
@Test
@Order(3)
void getAllProducts() {
testClient.get().uri("/products")
.exchange()
.expectStatus().isOk()
.expectBodyList(Product.class)
.hasSize(1);
}
}
\ No newline at end of file
package com.nisum.reactiveweb.repository;
import org.junit.jupiter.api.Test;
class ProductRepositoryTest {
@Test
void getProductBySku() {
}
@Test
void getAllProducts() {
}
@Test
void saveProduct() {
}
@Test
void updateProduct() {
}
@Test
void removeProduct() {
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment