From 88ea37c981bb68e0e59c0d22f021381e5335e1d3 Mon Sep 17 00:00:00 2001 From: balasr3 Date: Thu, 21 Sep 2023 23:59:34 +0530 Subject: [PATCH 1/3] BAEL-5889: Added code for Spy and SpyBean difference implementation --- .../baeldung/spytest/NotificationService.java | 11 +++++ .../main/java/com/baeldung/spytest/Order.java | 41 +++++++++++++++++++ .../com/baeldung/spytest/OrderRepository.java | 19 +++++++++ .../com/baeldung/spytest/OrderService.java | 21 ++++++++++ .../baeldung/spytest/SpyTestApplication.java | 12 ++++++ .../spytest/OrderServiceIntegrationTest.java | 32 +++++++++++++++ .../spytest/OrderServiceUnitTest.java | 39 ++++++++++++++++++ .../RunApplicationIntegrationTest.java | 1 + 8 files changed, 176 insertions(+) create mode 100644 spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/NotificationService.java create mode 100644 spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/Order.java create mode 100644 spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/OrderRepository.java create mode 100644 spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/OrderService.java create mode 100644 spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/SpyTestApplication.java create mode 100644 spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/spytest/OrderServiceIntegrationTest.java create mode 100644 spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/spytest/OrderServiceUnitTest.java diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/NotificationService.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/NotificationService.java new file mode 100644 index 0000000000..521e3b076e --- /dev/null +++ b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/NotificationService.java @@ -0,0 +1,11 @@ +package com.baeldung.spytest; + +import org.springframework.stereotype.Component; + +@Component +public class NotificationService { + public void notify(Order order){ + System.out.println(order); + } + +} diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/Order.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/Order.java new file mode 100644 index 0000000000..b7d7fad9e3 --- /dev/null +++ b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/Order.java @@ -0,0 +1,41 @@ +package com.baeldung.spytest; + +import java.util.UUID; + +public class Order { + + private UUID id; + + private String name; + + private double orderQuantity; + + private String address; + + public Order(UUID id, String name, double orderQuantity, String address) { + this.id = id; + this.name = name; + this.orderQuantity = orderQuantity; + this.address = address; + } + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public String getName() { + return name; + } + + public double getOrderQuantity() { + return orderQuantity; + } + + public String getAddress() { + return address; + } +} diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/OrderRepository.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/OrderRepository.java new file mode 100644 index 0000000000..986f7abde2 --- /dev/null +++ b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/OrderRepository.java @@ -0,0 +1,19 @@ +package com.baeldung.spytest; + +import java.util.HashMap; +import java.util.UUID; + +import org.springframework.stereotype.Component; + +@Component +public class OrderRepository { + + public static final HashMap orders=new HashMap<>(); + + public Order save(Order order) { + UUID orderId = UUID.randomUUID(); + order.setId(orderId); + orders.put(UUID.randomUUID(), order); + return order; + } +} diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/OrderService.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/OrderService.java new file mode 100644 index 0000000000..d08c96f5ae --- /dev/null +++ b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/OrderService.java @@ -0,0 +1,21 @@ +package com.baeldung.spytest; + +import org.springframework.stereotype.Service; + +@Service +public class OrderService { + + public final OrderRepository orderRepository; + + public final NotificationService notificationService; + + public OrderService(OrderRepository orderRepository, NotificationService notificationService) { + this.orderRepository = orderRepository; + this.notificationService = notificationService; + } + public Order save(Order order) { + order = orderRepository.save(order); + notificationService.notify(order); + return order; + } +} diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/SpyTestApplication.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/SpyTestApplication.java new file mode 100644 index 0000000000..bb2d3dc7d2 --- /dev/null +++ b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/SpyTestApplication.java @@ -0,0 +1,12 @@ +package com.baeldung.spytest; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +@SpringBootApplication +public class SpyTestApplication { + + public static void main(String[] args) { + SpringApplication.run(SpyTestApplication.class, args); + } + +} diff --git a/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/spytest/OrderServiceIntegrationTest.java b/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/spytest/OrderServiceIntegrationTest.java new file mode 100644 index 0000000000..22b0388b13 --- /dev/null +++ b/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/spytest/OrderServiceIntegrationTest.java @@ -0,0 +1,32 @@ +package com.baeldung.spytest; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.SpyBean; + +@SpringBootTest +class OrderServiceIntegrationTest { + + @Autowired + OrderRepository orderRepository; + @SpyBean + NotificationService notificationService; + @SpyBean + OrderService orderService; + + @Test + void givenNotificationServiceIsUsingSpyBean_whenOrderServiceIsCalled_thenNotificationServiceSpyBeanShouldBeInvoked() { + + Order orderInput = new Order(null, "Test", 1.0, "17 St Andrews Croft, Leeds ,LS17 7TP"); + Order order = orderService.save(orderInput); + Assertions.assertNotNull(order); + Assertions.assertNotNull(order.getId()); + verify(notificationService).notify(any(Order.class)); + } + +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/spytest/OrderServiceUnitTest.java b/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/spytest/OrderServiceUnitTest.java new file mode 100644 index 0000000000..b8f18c804c --- /dev/null +++ b/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/spytest/OrderServiceUnitTest.java @@ -0,0 +1,39 @@ +package com.baeldung.spytest; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.verify; + +import java.util.UUID; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Spy; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +class OrderServiceUnitTest { + + @Spy + OrderRepository orderRepository; + @Spy + NotificationService notificationService; + @InjectMocks + OrderService orderService; + + @Test + void givenNotificationServiceIsUsingSpy_whenOrderServiceIsCalled_thenNotificationServiceSpyShouldBeInvoked() { + + UUID orderId = UUID.randomUUID(); + Order orderInput = new Order(orderId, "Test", 1.0, "17 St Andrews Croft, Leeds ,LS17 7TP"); + doReturn(orderInput).when(orderRepository) + .save(any()); + Order order = orderService.save(orderInput); + Assertions.assertNotNull(order); + Assertions.assertEquals(orderId, order.getId()); + verify(notificationService).notify(any(Order.class)); + } + +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/prevent/commandline/application/runner/execution/RunApplicationIntegrationTest.java b/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/prevent/commandline/application/runner/execution/RunApplicationIntegrationTest.java index 26a7339f1d..3a8b74829e 100644 --- a/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/prevent/commandline/application/runner/execution/RunApplicationIntegrationTest.java +++ b/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/prevent/commandline/application/runner/execution/RunApplicationIntegrationTest.java @@ -1,6 +1,7 @@ package com.baeldung.prevent.commandline.application.runner.execution; import org.junit.jupiter.api.Test; +import org.mockito.Spy; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.SpyBean; From 14f336cf1a3d249f5e4228116e93396f477464e6 Mon Sep 17 00:00:00 2001 From: balasr3 Date: Fri, 22 Sep 2023 00:01:01 +0530 Subject: [PATCH 2/3] BAEL-5889: Removed unnecessary change --- .../runner/execution/RunApplicationIntegrationTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/prevent/commandline/application/runner/execution/RunApplicationIntegrationTest.java b/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/prevent/commandline/application/runner/execution/RunApplicationIntegrationTest.java index 3a8b74829e..26a7339f1d 100644 --- a/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/prevent/commandline/application/runner/execution/RunApplicationIntegrationTest.java +++ b/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/prevent/commandline/application/runner/execution/RunApplicationIntegrationTest.java @@ -1,7 +1,6 @@ package com.baeldung.prevent.commandline.application.runner.execution; import org.junit.jupiter.api.Test; -import org.mockito.Spy; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.SpyBean; From f324a501654d71fa3cf1ae04cb4992bae27ba3b8 Mon Sep 17 00:00:00 2001 From: balasr3 Date: Sat, 23 Sep 2023 16:11:32 +0530 Subject: [PATCH 3/3] BAEL-5889: Updated with review comment to add another method inside @Spy which is served through a mock to demonstrate partial mock condition --- .../java/com/baeldung/spytest/ExternalAlertService.java | 6 ++++++ .../java/com/baeldung/spytest/NotificationService.java | 9 ++++++++- .../src/main/java/com/baeldung/spytest/Order.java | 8 ++++++++ .../main/java/com/baeldung/spytest/OrderRepository.java | 2 +- .../src/main/java/com/baeldung/spytest/OrderService.java | 4 ++++ .../java/com/baeldung/spytest/SpyTestApplication.java | 1 + .../baeldung/spytest/OrderServiceIntegrationTest.java | 3 +++ .../java/com/baeldung/spytest/OrderServiceUnitTest.java | 2 ++ 8 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/ExternalAlertService.java diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/ExternalAlertService.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/ExternalAlertService.java new file mode 100644 index 0000000000..fd321a0e68 --- /dev/null +++ b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/ExternalAlertService.java @@ -0,0 +1,6 @@ +package com.baeldung.spytest; + +public interface ExternalAlertService { + public boolean alert(Order order); + +} diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/NotificationService.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/NotificationService.java index 521e3b076e..f0b2f92bee 100644 --- a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/NotificationService.java +++ b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/NotificationService.java @@ -4,8 +4,15 @@ import org.springframework.stereotype.Component; @Component public class NotificationService { - public void notify(Order order){ + + private ExternalAlertService externalAlertService; + + public void notify(Order order) { System.out.println(order); } + public boolean raiseAlert(Order order) { + return externalAlertService.alert(order); + } + } diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/Order.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/Order.java index b7d7fad9e3..23f5a05e9d 100644 --- a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/Order.java +++ b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/Order.java @@ -8,6 +8,8 @@ public class Order { private String name; + private OrderType orderType; + private double orderQuantity; private String address; @@ -19,6 +21,10 @@ public class Order { this.address = address; } + public enum OrderType { + INDIVIDUAL, BULK; + } + public UUID getId() { return id; } @@ -39,3 +45,5 @@ public class Order { return address; } } + + diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/OrderRepository.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/OrderRepository.java index 986f7abde2..90fe5ba2b8 100644 --- a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/OrderRepository.java +++ b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/OrderRepository.java @@ -8,7 +8,7 @@ import org.springframework.stereotype.Component; @Component public class OrderRepository { - public static final HashMap orders=new HashMap<>(); + public static final HashMap orders = new HashMap<>(); public Order save(Order order) { UUID orderId = UUID.randomUUID(); diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/OrderService.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/OrderService.java index d08c96f5ae..47647b8721 100644 --- a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/OrderService.java +++ b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/OrderService.java @@ -13,9 +13,13 @@ public class OrderService { this.orderRepository = orderRepository; this.notificationService = notificationService; } + public Order save(Order order) { order = orderRepository.save(order); notificationService.notify(order); + if (!notificationService.raiseAlert(order)) { + throw new RuntimeException("Alert not raised"); + } return order; } } diff --git a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/SpyTestApplication.java b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/SpyTestApplication.java index bb2d3dc7d2..d8d81378df 100644 --- a/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/SpyTestApplication.java +++ b/spring-boot-modules/spring-boot-testing-2/src/main/java/com/baeldung/spytest/SpyTestApplication.java @@ -2,6 +2,7 @@ package com.baeldung.spytest; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; + @SpringBootApplication public class SpyTestApplication { diff --git a/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/spytest/OrderServiceIntegrationTest.java b/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/spytest/OrderServiceIntegrationTest.java index 22b0388b13..96c7b09dfc 100644 --- a/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/spytest/OrderServiceIntegrationTest.java +++ b/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/spytest/OrderServiceIntegrationTest.java @@ -1,6 +1,7 @@ package com.baeldung.spytest; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.verify; import org.junit.jupiter.api.Assertions; @@ -23,6 +24,8 @@ class OrderServiceIntegrationTest { void givenNotificationServiceIsUsingSpyBean_whenOrderServiceIsCalled_thenNotificationServiceSpyBeanShouldBeInvoked() { Order orderInput = new Order(null, "Test", 1.0, "17 St Andrews Croft, Leeds ,LS17 7TP"); + doReturn(true).when(notificationService) + .raiseAlert(any(Order.class)); Order order = orderService.save(orderInput); Assertions.assertNotNull(order); Assertions.assertNotNull(order.getId()); diff --git a/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/spytest/OrderServiceUnitTest.java b/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/spytest/OrderServiceUnitTest.java index b8f18c804c..21ae849bcf 100644 --- a/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/spytest/OrderServiceUnitTest.java +++ b/spring-boot-modules/spring-boot-testing-2/src/test/java/com/baeldung/spytest/OrderServiceUnitTest.java @@ -30,6 +30,8 @@ class OrderServiceUnitTest { Order orderInput = new Order(orderId, "Test", 1.0, "17 St Andrews Croft, Leeds ,LS17 7TP"); doReturn(orderInput).when(orderRepository) .save(any()); + doReturn(true).when(notificationService) + .raiseAlert(any(Order.class)); Order order = orderService.save(orderInput); Assertions.assertNotNull(order); Assertions.assertEquals(orderId, order.getId());