├── 00.code-after-preparation.md ├── 00.intermediate-code.md ├── 01.code-after-integration-test.md ├── 02.Final.md ├── LICENSE ├── README.md ├── UnitTestingWithSpringBootAndMockito-CourseGuide.pdf ├── images ├── BadTest.png ├── GoodTest.png └── TestPyramid.png ├── junit-5-course-guide.md ├── link.txt ├── pom.xml ├── readme.md ├── src ├── main │ ├── java │ │ └── com │ │ │ └── in28minutes │ │ │ └── unittesting │ │ │ └── unittesting │ │ │ ├── UnitTestingApplication.java │ │ │ ├── business │ │ │ ├── ItemBusinessService.java │ │ │ └── SomeBusinessImpl.java │ │ │ ├── controller │ │ │ ├── HelloWorldController.java │ │ │ └── ItemController.java │ │ │ ├── data │ │ │ ├── ItemRepository.java │ │ │ └── SomeDataService.java │ │ │ └── model │ │ │ └── Item.java │ └── resources │ │ ├── application.properties │ │ └── data.sql └── test │ ├── java │ └── com │ │ └── in28minutes │ │ └── unittesting │ │ └── unittesting │ │ ├── UnitTestingApplicationTests.java │ │ ├── business │ │ ├── ItemBusinessServiceTest.java │ │ ├── ListMockTest.java │ │ ├── SomeBusinessMockTest.java │ │ ├── SomeBusinessStubTest.java │ │ └── SomeBusinessTest.java │ │ ├── controller │ │ ├── HelloWorldControllerTest.java │ │ ├── ItemControllerIT.java │ │ └── ItemControllerTest.java │ │ ├── data │ │ └── ItemRepositoryTest.java │ │ └── spike │ │ ├── AssertJTest.java │ │ ├── HamcrestMatchersTest.java │ │ ├── JsonAssertTest.java │ │ └── JsonPathTest.java │ └── resources │ └── application.properties └── starting-code.md /00.code-after-preparation.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | ## Complete Code Example 6 | 7 | ### /src/main/java/com/in28minutes/springunittestingwithmockito/business/ItemService.java 8 | 9 | ```java 10 | package com.in28minutes.springunittestingwithmockito.business; 11 | 12 | import java.util.List; 13 | 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.stereotype.Component; 16 | 17 | import com.in28minutes.springunittestingwithmockito.data.ItemRepository; 18 | import com.in28minutes.springunittestingwithmockito.entity.Item; 19 | 20 | @Component 21 | public class ItemService { 22 | 23 | @Autowired 24 | private ItemRepository repository; 25 | 26 | public List calculateTotalValue() { 27 | 28 | List items = repository.findAll(); 29 | 30 | items.stream().forEach((item) -> { 31 | item.setValue(item.getPrice() * item.getQuantity()); 32 | }); 33 | 34 | return items; 35 | } 36 | 37 | public void insertItem() { 38 | 39 | } 40 | 41 | } 42 | ``` 43 | --- 44 | 45 | ### /src/main/java/com/in28minutes/springunittestingwithmockito/business/SomeBusinessService.java 46 | 47 | ```java 48 | package com.in28minutes.springunittestingwithmockito.business; 49 | 50 | import java.util.Arrays; 51 | 52 | import com.in28minutes.springunittestingwithmockito.data.SomeDataService; 53 | 54 | public class SomeBusinessService { 55 | 56 | private SomeDataService someData; 57 | 58 | public SomeBusinessService(SomeDataService someData) { 59 | super(); 60 | this.someData = someData; 61 | } 62 | 63 | public int calculateSum() { 64 | return Arrays.stream(someData.retrieveData()) 65 | .reduce(Integer::sum).orElse(0); 66 | } 67 | } 68 | ``` 69 | --- 70 | 71 | ### /src/main/java/com/in28minutes/springunittestingwithmockito/controller/ItemController.java 72 | 73 | ```java 74 | package com.in28minutes.springunittestingwithmockito.controller; 75 | 76 | import java.util.List; 77 | 78 | import org.springframework.beans.factory.annotation.Autowired; 79 | import org.springframework.web.bind.annotation.GetMapping; 80 | import org.springframework.web.bind.annotation.RestController; 81 | 82 | import com.in28minutes.springunittestingwithmockito.business.ItemService; 83 | import com.in28minutes.springunittestingwithmockito.entity.Item; 84 | 85 | @RestController 86 | public class ItemController { 87 | 88 | @Autowired 89 | private ItemService service; 90 | 91 | @GetMapping("/items") 92 | public List retrieveAllItems() { 93 | return service.calculateTotalValue(); 94 | } 95 | 96 | } 97 | ``` 98 | --- 99 | 100 | ### /src/main/java/com/in28minutes/springunittestingwithmockito/data/ItemRepository.java 101 | 102 | ```java 103 | package com.in28minutes.springunittestingwithmockito.data; 104 | 105 | import org.springframework.data.jpa.repository.JpaRepository; 106 | 107 | import com.in28minutes.springunittestingwithmockito.entity.Item; 108 | 109 | public interface ItemRepository extends JpaRepository{ 110 | 111 | } 112 | ``` 113 | --- 114 | 115 | ### /src/main/java/com/in28minutes/springunittestingwithmockito/data/SomeDataService.java 116 | 117 | ```java 118 | package com.in28minutes.springunittestingwithmockito.data; 119 | 120 | public class SomeDataService { 121 | public int[] retrieveData() { 122 | throw new RuntimeException("Unimplemented"); 123 | } 124 | } 125 | ``` 126 | --- 127 | 128 | ### /src/main/java/com/in28minutes/springunittestingwithmockito/entity/Item.java 129 | 130 | ```java 131 | package com.in28minutes.springunittestingwithmockito.entity; 132 | 133 | import javax.persistence.Entity; 134 | import javax.persistence.Id; 135 | import javax.persistence.Transient; 136 | 137 | @Entity 138 | public class Item { 139 | @Id 140 | private long id; 141 | private String name; 142 | private int quantity; 143 | private int price; 144 | 145 | @Transient 146 | private long value; 147 | 148 | public Item() { 149 | 150 | } 151 | 152 | public Item(int id, String name, int quantity, int price) { 153 | super(); 154 | this.id = id; 155 | this.name = name; 156 | this.quantity = quantity; 157 | this.price = price; 158 | } 159 | 160 | public long getId() { 161 | return id; 162 | } 163 | 164 | public void setId(long id) { 165 | this.id = id; 166 | } 167 | 168 | public String getName() { 169 | return name; 170 | } 171 | 172 | public void setName(String name) { 173 | this.name = name; 174 | } 175 | 176 | public int getQuantity() { 177 | return quantity; 178 | } 179 | 180 | public void setQuantity(int quantity) { 181 | this.quantity = quantity; 182 | } 183 | 184 | public int getPrice() { 185 | return price; 186 | } 187 | 188 | public void setPrice(int price) { 189 | this.price = price; 190 | } 191 | 192 | public long getValue() { 193 | return value; 194 | } 195 | 196 | public void setValue(long value) { 197 | this.value = value; 198 | } 199 | 200 | } 201 | ``` 202 | --- 203 | 204 | ### /src/main/java/com/in28minutes/springunittestingwithmockito/SpringUnitTestingWithMockitoApplication.java 205 | 206 | ```java 207 | package com.in28minutes.springunittestingwithmockito; 208 | 209 | import org.springframework.boot.SpringApplication; 210 | import org.springframework.boot.autoconfigure.SpringBootApplication; 211 | 212 | @SpringBootApplication 213 | public class SpringUnitTestingWithMockitoApplication { 214 | 215 | public static void main(String[] args) { 216 | SpringApplication.run(SpringUnitTestingWithMockitoApplication.class, args); 217 | } 218 | } 219 | ``` 220 | --- 221 | 222 | ### /src/main/resources/application.properties 223 | 224 | ```properties 225 | spring.h2.console.enabled=true 226 | spring.jpa.show-sql=true 227 | ``` 228 | --- 229 | 230 | ### /src/main/resources/data.sql 231 | 232 | ``` 233 | insert into item (id, name, quantity, price) values(10001, 'Chocolates', 25, 2); 234 | insert into item (id, name, quantity, price) values(10002, 'Biscuits', 50, 2); 235 | insert into item (id, name, quantity, price) values(10003, 'Pens', 25, 3); 236 | insert into item (id, name, quantity, price) values(10004, 'Pencils', 25, 2); 237 | ``` 238 | --- 239 | 240 | ### /src/test/java/com/in28minutes/springunittestingwithmockito/AssertjTest.java 241 | 242 | ```java 243 | package com.in28minutes.springunittestingwithmockito; 244 | 245 | import static org.assertj.core.api.Assertions.assertThat; 246 | 247 | import java.util.Arrays; 248 | import java.util.List; 249 | 250 | import org.junit.Test; 251 | 252 | public class AssertjTest { 253 | 254 | @Test 255 | public void basicHamcrestMatchers() { 256 | //List 257 | List scores = Arrays.asList(99, 100, 101, 105); 258 | 259 | assertThat(scores).hasSize(4); 260 | assertThat(scores).contains(100, 101); 261 | assertThat(scores).allMatch(x -> x > 90); 262 | assertThat(scores).allMatch(x -> x < 200); 263 | 264 | // String 265 | assertThat("").isEmpty(); 266 | 267 | // Array 268 | Integer[] marks = { 1, 2, 3 }; 269 | 270 | assertThat(marks).hasSize(3); 271 | assertThat(marks).contains(2, 3, 1); 272 | 273 | } 274 | } 275 | ``` 276 | --- 277 | 278 | ### /src/test/java/com/in28minutes/springunittestingwithmockito/business/ItemServiceTest.java 279 | 280 | ```java 281 | package com.in28minutes.springunittestingwithmockito.business; 282 | 283 | import static org.junit.Assert.assertEquals; 284 | import static org.mockito.Mockito.when; 285 | 286 | import java.util.ArrayList; 287 | import java.util.Arrays; 288 | import java.util.List; 289 | 290 | import org.junit.Test; 291 | import org.junit.runner.RunWith; 292 | import org.mockito.InjectMocks; 293 | import org.mockito.Mock; 294 | import org.mockito.junit.MockitoJUnitRunner; 295 | 296 | import com.in28minutes.springunittestingwithmockito.data.ItemRepository; 297 | import com.in28minutes.springunittestingwithmockito.entity.Item; 298 | 299 | @RunWith(MockitoJUnitRunner.class) 300 | public class ItemServiceTest { 301 | 302 | @Mock 303 | ItemRepository repository; 304 | 305 | @InjectMocks 306 | ItemService service; 307 | 308 | @Test 309 | public void testWithMock_usingMockitoRunner() { 310 | List mockList = Arrays.asList(new Item(1, "Dummy", 10, 5)); 311 | 312 | when(repository.findAll()).thenReturn(mockList); 313 | 314 | List items = service.calculateTotalValue(); 315 | assertEquals(50,items.get(0).getValue()); 316 | } 317 | } 318 | ``` 319 | --- 320 | 321 | ### /src/test/java/com/in28minutes/springunittestingwithmockito/business/SomeBusinessServiceTest.java 322 | 323 | ```java 324 | package com.in28minutes.springunittestingwithmockito.business; 325 | 326 | import static org.junit.Assert.assertEquals; 327 | import static org.mockito.Mockito.mock; 328 | import static org.mockito.Mockito.when; 329 | 330 | import org.junit.Test; 331 | import org.junit.runner.RunWith; 332 | import org.mockito.InjectMocks; 333 | import org.mockito.Mock; 334 | import org.mockito.junit.MockitoJUnitRunner; 335 | 336 | import com.in28minutes.springunittestingwithmockito.data.SomeDataService; 337 | 338 | @RunWith(MockitoJUnitRunner.class) 339 | public class SomeBusinessServiceTest { 340 | 341 | @Mock 342 | SomeDataService dataService; 343 | 344 | @InjectMocks 345 | SomeBusinessService businessService; 346 | 347 | @Test(expected=Exception.class) 348 | public void testWithExpectedException() { 349 | SomeDataService dataService = new SomeDataService(); 350 | SomeBusinessService businessService = 351 | new SomeBusinessService(dataService); 352 | businessService.calculateSum(); 353 | } 354 | 355 | @Test 356 | public void testWithMock() { 357 | SomeDataService dataService = mock(SomeDataService.class); 358 | when(dataService.retrieveData()).thenReturn(new int[] {10,20}); 359 | SomeBusinessService businessService = 360 | new SomeBusinessService(dataService); 361 | assertEquals(30,businessService.calculateSum()); 362 | } 363 | 364 | @Test 365 | public void playWithListClass() { 366 | 367 | } 368 | 369 | @Test 370 | public void testWithMock_usingMockitoRunner() { 371 | when(dataService.retrieveData()).thenReturn(new int[] {10,20}); 372 | assertEquals(30,businessService.calculateSum()); 373 | } 374 | 375 | @Test 376 | public void mockitoRunnerUnderstandSpringAutowiringToo() { 377 | 378 | } 379 | } 380 | ``` 381 | --- 382 | 383 | ### /src/test/java/com/in28minutes/springunittestingwithmockito/controller/ItemControllerIT.java 384 | 385 | ```java 386 | package com.in28minutes.springunittestingwithmockito.controller; 387 | 388 | import static org.assertj.core.api.Assertions.assertThat; 389 | 390 | import org.junit.Test; 391 | import org.junit.runner.RunWith; 392 | import org.springframework.beans.factory.annotation.Autowired; 393 | import org.springframework.boot.test.context.SpringBootTest; 394 | import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; 395 | import org.springframework.boot.test.web.client.TestRestTemplate; 396 | import org.springframework.test.context.junit4.SpringRunner; 397 | 398 | @RunWith(SpringRunner.class) 399 | @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) 400 | public class ItemControllerIT { 401 | 402 | @Autowired 403 | private TestRestTemplate restTemplate; 404 | 405 | @Test 406 | public void exampleTest2() { 407 | String body = this.restTemplate.getForObject("/items", String.class); 408 | assertThat(body).contains("Pencil"); 409 | } 410 | } 411 | ``` 412 | --- 413 | 414 | ### /src/test/java/com/in28minutes/springunittestingwithmockito/controller/ItemControllerTest.java 415 | 416 | ```java 417 | package com.in28minutes.springunittestingwithmockito.controller; 418 | 419 | import static org.mockito.Mockito.when; 420 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 421 | 422 | import java.util.Arrays; 423 | import java.util.List; 424 | 425 | import org.junit.Test; 426 | import org.junit.runner.RunWith; 427 | import org.skyscreamer.jsonassert.JSONAssert; 428 | import org.springframework.beans.factory.annotation.Autowired; 429 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 430 | import org.springframework.boot.test.mock.mockito.MockBean; 431 | import org.springframework.http.MediaType; 432 | import org.springframework.test.context.junit4.SpringRunner; 433 | import org.springframework.test.web.servlet.MockMvc; 434 | import org.springframework.test.web.servlet.MvcResult; 435 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; 436 | 437 | import com.in28minutes.springunittestingwithmockito.business.ItemService; 438 | import com.in28minutes.springunittestingwithmockito.entity.Item; 439 | 440 | @RunWith(SpringRunner.class) 441 | @WebMvcTest(value = ItemController.class) 442 | public class ItemControllerTest { 443 | 444 | @Autowired 445 | private MockMvc mvc; 446 | 447 | @MockBean 448 | private ItemService service; 449 | 450 | @Test 451 | public void retrieveItems() throws Exception { 452 | List mockList = Arrays.asList(new Item(1, "Dummy", 10, 5)); 453 | when(service.calculateTotalValue()).thenReturn(mockList); 454 | MvcResult result = mvc.perform(MockMvcRequestBuilders.get("/items").accept(MediaType.APPLICATION_JSON)) 455 | .andExpect(status().isOk()).andReturn(); 456 | String expected = "[" + "{id:1,name:Dummy}" + "]"; 457 | JSONAssert.assertEquals(expected, result.getResponse().getContentAsString(), false); 458 | } 459 | } 460 | ``` 461 | --- 462 | 463 | ### /src/test/java/com/in28minutes/springunittestingwithmockito/data/ItemRepositoryTest.java 464 | 465 | ```java 466 | package com.in28minutes.springunittestingwithmockito.data; 467 | 468 | import static org.assertj.core.api.Assertions.assertThat; 469 | 470 | import java.util.List; 471 | 472 | import org.junit.Test; 473 | import org.junit.runner.RunWith; 474 | import org.springframework.beans.factory.annotation.Autowired; 475 | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; 476 | import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; 477 | import org.springframework.test.context.junit4.SpringRunner; 478 | 479 | import com.in28minutes.springunittestingwithmockito.entity.Item; 480 | 481 | @RunWith(SpringRunner.class) 482 | @DataJpaTest 483 | public class ItemRepositoryTest { 484 | 485 | @Autowired 486 | private TestEntityManager entityManager; 487 | 488 | @Autowired 489 | private ItemRepository repository; 490 | 491 | @Test 492 | public void testExample() throws Exception { 493 | List items = this.repository.findAll(); 494 | assertThat(items.size()).isEqualTo(4); 495 | } 496 | 497 | } 498 | ``` 499 | --- 500 | 501 | ### /src/test/java/com/in28minutes/springunittestingwithmockito/HamcrestMatcherTest.java 502 | 503 | ```java 504 | package com.in28minutes.springunittestingwithmockito; 505 | 506 | import static org.hamcrest.CoreMatchers.hasItems; 507 | import static org.hamcrest.MatcherAssert.assertThat; 508 | import static org.hamcrest.Matchers.arrayContainingInAnyOrder; 509 | import static org.hamcrest.Matchers.arrayWithSize; 510 | import static org.hamcrest.Matchers.greaterThan; 511 | import static org.hamcrest.Matchers.hasSize; 512 | import static org.hamcrest.Matchers.isEmptyString; 513 | import static org.hamcrest.Matchers.lessThan; 514 | import static org.hamcrest.core.Every.everyItem; 515 | 516 | import java.util.Arrays; 517 | import java.util.List; 518 | 519 | import org.junit.Test; 520 | 521 | public class HamcrestMatcherTest { 522 | 523 | @Test 524 | public void basicHamcrestMatchers() { 525 | 526 | //List 527 | List scores = Arrays.asList(99, 100, 101, 105); 528 | assertThat(scores, hasSize(4)); 529 | assertThat(scores, hasItems(100, 101)); 530 | assertThat(scores, everyItem(greaterThan(90))); 531 | assertThat(scores, everyItem(lessThan(200))); 532 | 533 | // String 534 | assertThat("", isEmptyString()); 535 | 536 | // Array 537 | Integer[] marks = { 1, 2, 3 }; 538 | 539 | assertThat(marks, arrayWithSize(3)); 540 | assertThat(marks, arrayContainingInAnyOrder(2, 3, 1)); 541 | 542 | } 543 | } 544 | ``` 545 | --- 546 | 547 | ### /src/test/java/com/in28minutes/springunittestingwithmockito/JsonAssertTest.java 548 | 549 | ```java 550 | package com.in28minutes.springunittestingwithmockito; 551 | 552 | import org.json.JSONException; 553 | import org.junit.Test; 554 | import org.skyscreamer.jsonassert.JSONAssert; 555 | 556 | public class JsonAssertTest { 557 | @Test 558 | public void jsonAssertTest() throws JSONException { 559 | String responseFromService = "[{\"id\":10001,\"name\":\"Chocolates\",\"quantity\":25,\"price\":2,\"value\":50}," 560 | + "{\"id\":10002,\"name\":\"Biscuits\",\"quantity\":50,\"price\":2,\"value\":100}," 561 | + "{\"id\":10003,\"name\":\"Pens\",\"quantity\":25,\"price\":3,\"value\":75}," 562 | + "{\"id\":10004,\"name\":\"Pencils\",\"quantity\":25,\"price\":2,\"value\":50}]"; 563 | 564 | JSONAssert.assertEquals("[{id:10004,name:Pencils},{},{},{}]", responseFromService, false); 565 | 566 | // Strict true 567 | // 1. Checks all elements 568 | // 2. Order in arrays becomes important 569 | 570 | // Easy to read error messages 571 | } 572 | 573 | } 574 | ``` 575 | --- 576 | 577 | ### /src/test/java/com/in28minutes/springunittestingwithmockito/JsonPathTest.java 578 | 579 | ```java 580 | package com.in28minutes.springunittestingwithmockito; 581 | 582 | import static org.assertj.core.api.Assertions.assertThat; 583 | 584 | import java.util.List; 585 | 586 | import org.junit.Test; 587 | 588 | import com.jayway.jsonpath.JsonPath; 589 | import com.jayway.jsonpath.ReadContext; 590 | 591 | public class JsonPathTest { 592 | @Test 593 | public void jsonAssertTest() { 594 | String responseFromService = "[{\"id\":10001,\"name\":\"Chocolates\",\"quantity\":25,\"price\":2,\"value\":50}," 595 | + "{\"id\":10002,\"name\":\"Biscuits\",\"quantity\":50,\"price\":2,\"value\":100}," 596 | + "{\"id\":10003,\"name\":\"Pens\",\"quantity\":25,\"price\":3,\"value\":75}," 597 | + "{\"id\":10004,\"name\":\"Pencils\",\"quantity\":25,\"price\":2,\"value\":50}]"; 598 | 599 | ReadContext ctx = JsonPath.parse(responseFromService); 600 | 601 | List allIds = ctx.read("$..id"); 602 | assertThat(allIds).containsExactly(10001,10002,10003,10004); 603 | System.out.println(ctx.read("$.length()]").toString()); 604 | System.out.println(ctx.read("$.[2]").toString()); 605 | System.out.println(ctx.read("$.[0:2]").toString());//0 inclusive 2 exclusive 606 | System.out.println(ctx.read("$[?(@.quantity==50)]").toString()); 607 | } 608 | 609 | } 610 | ``` 611 | --- 612 | 613 | ### /src/test/java/com/in28minutes/springunittestingwithmockito/ListTest.java 614 | 615 | ```java 616 | package com.in28minutes.springunittestingwithmockito; 617 | 618 | import static org.junit.Assert.assertEquals; 619 | import static org.junit.Assert.assertNull; 620 | import static org.mockito.Mockito.mock; 621 | import static org.mockito.Mockito.when; 622 | 623 | import java.util.List; 624 | 625 | import org.junit.Test; 626 | import org.mockito.Mockito; 627 | 628 | public class ListTest { 629 | 630 | @Test 631 | public void letsMockListSize() { 632 | List list = mock(List.class); 633 | when(list.size()).thenReturn(10); 634 | assertEquals(10, list.size()); 635 | } 636 | 637 | @Test 638 | public void letsMockListSizeWithMultipleReturnValues() { 639 | List list = mock(List.class); 640 | when(list.size()).thenReturn(10).thenReturn(20); 641 | assertEquals(10, list.size()); // First Call 642 | assertEquals(20, list.size()); // Second Call 643 | } 644 | 645 | @Test 646 | public void letsMockListGet() { 647 | List list = mock(List.class); 648 | when(list.get(0)).thenReturn("in28Minutes"); 649 | assertEquals("in28Minutes", list.get(0)); 650 | assertNull(list.get(1)); 651 | } 652 | 653 | @Test(expected = RuntimeException.class) 654 | public void letsMockListGetToThrowException() { 655 | List list = mock(List.class); 656 | when(list.get(Mockito.anyInt())).thenThrow( 657 | new RuntimeException("Something went wrong")); 658 | list.get(0); 659 | } 660 | 661 | @Test 662 | public void letsMockListGetWithAny() { 663 | List list = mock(List.class); 664 | Mockito.when(list.get(Mockito.anyInt())).thenReturn("in28Minutes"); 665 | // If you are using argument matchers, all arguments 666 | // have to be provided by matchers. 667 | assertEquals("in28Minutes", list.get(0)); 668 | assertEquals("in28Minutes", list.get(1)); 669 | } 670 | } 671 | ``` 672 | --- 673 | 674 | ### /src/test/java/com/in28minutes/springunittestingwithmockito/SpringUnitTestingWithMockitoApplicationTests.java 675 | 676 | ```java 677 | package com.in28minutes.springunittestingwithmockito; 678 | 679 | import static org.mockito.Mockito.when; 680 | 681 | import java.util.ArrayList; 682 | import java.util.List; 683 | 684 | import org.junit.Test; 685 | import org.junit.runner.RunWith; 686 | import org.springframework.beans.factory.annotation.Autowired; 687 | import org.springframework.boot.test.context.SpringBootTest; 688 | import org.springframework.boot.test.mock.mockito.MockBean; 689 | import org.springframework.test.context.junit4.SpringRunner; 690 | 691 | import com.in28minutes.springunittestingwithmockito.business.ItemService; 692 | import com.in28minutes.springunittestingwithmockito.data.ItemRepository; 693 | import com.in28minutes.springunittestingwithmockito.entity.Item; 694 | 695 | @RunWith(SpringRunner.class) 696 | @SpringBootTest 697 | public class SpringUnitTestingWithMockitoApplicationTests { 698 | 699 | @MockBean 700 | ItemRepository repository; 701 | 702 | @Autowired 703 | ItemService service; 704 | 705 | @Test 706 | public void contextLoads() { 707 | List asList = new ArrayList(); 708 | asList.add(new Item(1, "Dummy", 10, 5)); 709 | 710 | when(repository.findAll()).thenReturn(asList); 711 | 712 | System.out.println(service.calculateTotalValue()); 713 | } 714 | 715 | } 716 | ``` 717 | --- 718 | -------------------------------------------------------------------------------- /00.intermediate-code.md: -------------------------------------------------------------------------------- 1 | ### Basic Mocking with mock 2 | ```java 3 | package com.in28minutes.unittesting.unittesting.business; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | import static org.mockito.Mockito.mock; 7 | import static org.mockito.Mockito.when; 8 | 9 | import org.junit.Test; 10 | 11 | import com.in28minutes.unittesting.unittesting.data.SomeDataService; 12 | 13 | public class SomeBusinessMockTest { 14 | 15 | @Test 16 | public void calculateSumUsingDataService_basic() { 17 | SomeBusinessImpl business = new SomeBusinessImpl(); 18 | SomeDataService dataServiceMock = mock(SomeDataService.class); 19 | when(dataServiceMock.retrieveAllData()).thenReturn(new int[] { 1, 2, 3 }); 20 | 21 | business.setSomeDataService(dataServiceMock); 22 | int actualResult = business.calculateSumUsingDataService(); 23 | int expectedResult = 6; 24 | assertEquals(expectedResult, actualResult); 25 | } 26 | 27 | @Test 28 | public void calculateSumUsingDataService_empty() { 29 | SomeBusinessImpl business = new SomeBusinessImpl(); 30 | SomeDataService dataServiceMock = mock(SomeDataService.class); 31 | when(dataServiceMock.retrieveAllData()).thenReturn(new int[] { }); 32 | 33 | business.setSomeDataService(dataServiceMock); 34 | int actualResult = business.calculateSumUsingDataService();//new int[] {} 35 | int expectedResult = 0; 36 | assertEquals(expectedResult, actualResult); 37 | } 38 | 39 | @Test 40 | public void calculateSumUsingDataService_oneValue() { 41 | SomeBusinessImpl business = new SomeBusinessImpl(); 42 | SomeDataService dataServiceMock = mock(SomeDataService.class); 43 | when(dataServiceMock.retrieveAllData()).thenReturn(new int[] { 1, 2, 3 }); 44 | 45 | business.setSomeDataService(dataServiceMock); 46 | int actualResult = business.calculateSumUsingDataService();//new int[] { 5 } 47 | int expectedResult = 5; 48 | assertEquals(expectedResult, actualResult); 49 | } 50 | } 51 | ``` 52 | 53 | ### Removing Duplication 54 | 55 | ```java 56 | package com.in28minutes.unittesting.unittesting.business; 57 | 58 | import static org.junit.Assert.assertEquals; 59 | import static org.mockito.Mockito.mock; 60 | import static org.mockito.Mockito.when; 61 | 62 | import org.junit.Before; 63 | import org.junit.Test; 64 | 65 | import com.in28minutes.unittesting.unittesting.data.SomeDataService; 66 | 67 | public class SomeBusinessMockTest { 68 | 69 | SomeBusinessImpl business = new SomeBusinessImpl(); 70 | SomeDataService dataServiceMock = mock(SomeDataService.class); 71 | 72 | @Before 73 | public void before() { 74 | business.setSomeDataService(dataServiceMock); 75 | } 76 | 77 | @Test 78 | public void calculateSumUsingDataService_basic() { 79 | when(dataServiceMock.retrieveAllData()).thenReturn(new int[] { 1, 2, 3 }); 80 | assertEquals(6, business.calculateSumUsingDataService()); 81 | } 82 | 83 | @Test 84 | public void calculateSumUsingDataService_empty() { 85 | when(dataServiceMock.retrieveAllData()).thenReturn(new int[] {}); 86 | assertEquals(0, business.calculateSumUsingDataService()); 87 | } 88 | 89 | @Test 90 | public void calculateSumUsingDataService_oneValue() { 91 | when(dataServiceMock.retrieveAllData()).thenReturn(new int[] { 5 }); 92 | assertEquals(5, business.calculateSumUsingDataService()); 93 | } 94 | } 95 | ``` 96 | 97 | -------------------------------------------------------------------------------- /01.code-after-integration-test.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | ## Complete Code Example 6 | 7 | 8 | ### /src/main/java/com/in28minutes/unittesting/unittesting/business/ItemBusinessService.java 9 | 10 | ```java 11 | package com.in28minutes.unittesting.unittesting.business; 12 | 13 | import java.util.List; 14 | 15 | import org.springframework.beans.factory.annotation.Autowired; 16 | import org.springframework.stereotype.Component; 17 | 18 | import com.in28minutes.unittesting.unittesting.data.ItemRepository; 19 | import com.in28minutes.unittesting.unittesting.model.Item; 20 | 21 | @Component 22 | public class ItemBusinessService { 23 | 24 | @Autowired 25 | private ItemRepository repository; 26 | 27 | public Item retreiveHardcodedItem() { 28 | return new Item(1, "Ball", 10, 100); 29 | } 30 | 31 | public List retrieveAllItems() { 32 | List items = repository.findAll(); 33 | 34 | for(Item item:items) { 35 | item.setValue(item.getPrice() * item.getQuantity()); 36 | } 37 | 38 | return items; 39 | } 40 | 41 | } 42 | ``` 43 | --- 44 | 45 | ### /src/main/java/com/in28minutes/unittesting/unittesting/business/SomeBusinessImpl.java 46 | 47 | ```java 48 | package com.in28minutes.unittesting.unittesting.business; 49 | 50 | import com.in28minutes.unittesting.unittesting.data.SomeDataService; 51 | 52 | public class SomeBusinessImpl { 53 | 54 | private SomeDataService someDataService; 55 | 56 | public void setSomeDataService(SomeDataService someDataService) { 57 | this.someDataService = someDataService; 58 | } 59 | 60 | public int calculateSum(int[] data) { 61 | int sum = 0; 62 | for(int value:data) { 63 | sum += value; 64 | } 65 | return sum; 66 | } 67 | 68 | public int calculateSumUsingDataService() { 69 | int sum = 0; 70 | int[] data = someDataService.retrieveAllData(); 71 | for(int value:data) { 72 | sum += value; 73 | } 74 | 75 | //someDataService.storeSum(sum); 76 | return sum; 77 | } 78 | 79 | } 80 | ``` 81 | --- 82 | 83 | ### /src/main/java/com/in28minutes/unittesting/unittesting/controller/HelloWorldController.java 84 | 85 | ```java 86 | package com.in28minutes.unittesting.unittesting.controller; 87 | 88 | import org.springframework.web.bind.annotation.GetMapping; 89 | import org.springframework.web.bind.annotation.RestController; 90 | 91 | @RestController 92 | public class HelloWorldController { 93 | 94 | @GetMapping("/hello-world") 95 | public String helloWorld() { 96 | return "Hello World"; 97 | } 98 | 99 | } 100 | ``` 101 | --- 102 | 103 | ### /src/main/java/com/in28minutes/unittesting/unittesting/controller/ItemController.java 104 | 105 | ```java 106 | package com.in28minutes.unittesting.unittesting.controller; 107 | 108 | import java.util.List; 109 | 110 | import org.springframework.beans.factory.annotation.Autowired; 111 | import org.springframework.web.bind.annotation.GetMapping; 112 | import org.springframework.web.bind.annotation.RestController; 113 | 114 | import com.in28minutes.unittesting.unittesting.business.ItemBusinessService; 115 | import com.in28minutes.unittesting.unittesting.model.Item; 116 | 117 | @RestController 118 | public class ItemController { 119 | 120 | @Autowired 121 | private ItemBusinessService businessService; 122 | 123 | @GetMapping("/dummy-item") 124 | public Item dummyItem() { 125 | return new Item(1, "Ball", 10, 100); 126 | } 127 | 128 | @GetMapping("/item-from-business-service") 129 | public Item itemFromBusinessService() { 130 | 131 | Item item = businessService.retreiveHardcodedItem(); 132 | 133 | return item; 134 | } 135 | 136 | @GetMapping("/all-items-from-database") 137 | public List retrieveAllItems() { 138 | return businessService.retrieveAllItems(); 139 | } 140 | 141 | } 142 | ``` 143 | --- 144 | 145 | ### /src/main/java/com/in28minutes/unittesting/unittesting/data/ItemRepository.java 146 | 147 | ```java 148 | package com.in28minutes.unittesting.unittesting.data; 149 | 150 | import org.springframework.data.jpa.repository.JpaRepository; 151 | 152 | import com.in28minutes.unittesting.unittesting.model.Item; 153 | 154 | public interface ItemRepository extends JpaRepository{ 155 | 156 | } 157 | ``` 158 | --- 159 | 160 | ### /src/main/java/com/in28minutes/unittesting/unittesting/data/SomeDataService.java 161 | 162 | ```java 163 | package com.in28minutes.unittesting.unittesting.data; 164 | 165 | public interface SomeDataService { 166 | 167 | int[] retrieveAllData(); 168 | 169 | //int retrieveSpecificData(); 170 | 171 | } 172 | ``` 173 | --- 174 | 175 | ### /src/main/java/com/in28minutes/unittesting/unittesting/model/Item.java 176 | 177 | ```java 178 | package com.in28minutes.unittesting.unittesting.model; 179 | 180 | import javax.persistence.Entity; 181 | import javax.persistence.Id; 182 | import javax.persistence.Transient; 183 | 184 | @Entity 185 | public class Item { 186 | 187 | @Id 188 | private int id; 189 | private String name; 190 | private int price; 191 | private int quantity; 192 | 193 | @Transient 194 | private int value; 195 | 196 | protected Item() { 197 | 198 | } 199 | 200 | public Item(int id, String name, int price, int quantity) { 201 | this.id = id; 202 | this.name = name; 203 | this.price = price; 204 | this.quantity = quantity; 205 | } 206 | 207 | public int getId() { 208 | return id; 209 | } 210 | 211 | public String getName() { 212 | return name; 213 | } 214 | 215 | public int getPrice() { 216 | return price; 217 | } 218 | 219 | public int getQuantity() { 220 | return quantity; 221 | } 222 | 223 | public int getValue() { 224 | return value; 225 | } 226 | 227 | public void setValue(int value) { 228 | this.value = value; 229 | } 230 | 231 | public String toString() { 232 | return String.format("Item[%d, %s, %d, %d]", id, name, price, quantity); 233 | } 234 | } 235 | ``` 236 | --- 237 | 238 | ### /src/main/java/com/in28minutes/unittesting/unittesting/UnitTestingApplication.java 239 | 240 | ```java 241 | package com.in28minutes.unittesting.unittesting; 242 | 243 | import org.springframework.boot.SpringApplication; 244 | import org.springframework.boot.autoconfigure.SpringBootApplication; 245 | 246 | @SpringBootApplication 247 | public class UnitTestingApplication { 248 | 249 | public static void main(String[] args) { 250 | SpringApplication.run(UnitTestingApplication.class, args); 251 | } 252 | } 253 | ``` 254 | --- 255 | 256 | ### /src/main/resources/application.properties 257 | 258 | ```properties 259 | spring.jpa.show-sql=true 260 | spring.h2.console.enabled=true 261 | ``` 262 | --- 263 | 264 | ### /src/main/resources/data.sql 265 | 266 | ``` 267 | insert into item(id, name, price, quantity) values(10001,'Item1',10,20); 268 | insert into item(id, name, price, quantity) values(10002,'Item2',5,10); 269 | insert into item(id, name, price, quantity) values(10003,'Item3',15,2); 270 | ``` 271 | --- 272 | 273 | ### /src/test/java/com/in28minutes/unittesting/unittesting/business/ItemBusinessServiceTest.java 274 | 275 | ```java 276 | package com.in28minutes.unittesting.unittesting.business; 277 | 278 | import static org.junit.Assert.assertEquals; 279 | import static org.mockito.Mockito.when; 280 | 281 | import java.util.Arrays; 282 | import java.util.List; 283 | 284 | import org.junit.Test; 285 | import org.junit.runner.RunWith; 286 | import org.mockito.InjectMocks; 287 | import org.mockito.Mock; 288 | import org.mockito.junit.MockitoJUnitRunner; 289 | 290 | import com.in28minutes.unittesting.unittesting.data.ItemRepository; 291 | import com.in28minutes.unittesting.unittesting.model.Item; 292 | 293 | @RunWith(MockitoJUnitRunner.class) 294 | public class ItemBusinessServiceTest { 295 | 296 | @InjectMocks 297 | private ItemBusinessService business; 298 | 299 | @Mock 300 | private ItemRepository repository; 301 | 302 | @Test 303 | public void retrieveAllItems_basic() { 304 | when(repository.findAll()).thenReturn(Arrays.asList(new Item(2,"Item2",10,10), 305 | new Item(3,"Item3",20,20))); 306 | List items = business.retrieveAllItems(); 307 | 308 | assertEquals(100, items.get(0).getValue()); 309 | assertEquals(400, items.get(1).getValue()); 310 | } 311 | } 312 | ``` 313 | --- 314 | 315 | ### /src/test/java/com/in28minutes/unittesting/unittesting/business/ListMockTest.java 316 | 317 | ```java 318 | package com.in28minutes.unittesting.unittesting.business; 319 | 320 | import static org.junit.Assert.assertEquals; 321 | import static org.mockito.ArgumentMatchers.anyInt; 322 | import static org.mockito.Mockito.atLeast; 323 | import static org.mockito.Mockito.atLeastOnce; 324 | import static org.mockito.Mockito.atMost; 325 | import static org.mockito.Mockito.mock; 326 | import static org.mockito.Mockito.never; 327 | import static org.mockito.Mockito.spy; 328 | import static org.mockito.Mockito.times; 329 | import static org.mockito.Mockito.verify; 330 | import static org.mockito.Mockito.when; 331 | 332 | import java.util.ArrayList; 333 | import java.util.List; 334 | 335 | import org.junit.Test; 336 | import org.mockito.ArgumentCaptor; 337 | 338 | public class ListMockTest { 339 | 340 | List mock = mock(List.class); 341 | 342 | @Test 343 | public void size_basic() { 344 | when(mock.size()).thenReturn(5); 345 | assertEquals(5, mock.size()); 346 | } 347 | 348 | @Test 349 | public void returnDifferentValues() { 350 | when(mock.size()).thenReturn(5).thenReturn(10); 351 | assertEquals(5, mock.size()); 352 | assertEquals(10, mock.size()); 353 | } 354 | 355 | @Test 356 | public void returnWithParameters() { 357 | when(mock.get(0)).thenReturn("in28Minutes"); 358 | assertEquals("in28Minutes", mock.get(0)); 359 | assertEquals(null, mock.get(1)); 360 | } 361 | 362 | @Test 363 | public void returnWithGenericParameters() { 364 | when(mock.get(anyInt())).thenReturn("in28Minutes"); 365 | 366 | assertEquals("in28Minutes", mock.get(0)); 367 | assertEquals("in28Minutes", mock.get(1)); 368 | } 369 | 370 | @Test 371 | public void verificationBasics() { 372 | // SUT 373 | String value1 = mock.get(0); 374 | String value2 = mock.get(1); 375 | 376 | // Verify 377 | verify(mock).get(0); 378 | verify(mock, times(2)).get(anyInt()); 379 | verify(mock, atLeast(1)).get(anyInt()); 380 | verify(mock, atLeastOnce()).get(anyInt()); 381 | verify(mock, atMost(2)).get(anyInt()); 382 | verify(mock, never()).get(2); 383 | } 384 | 385 | @Test 386 | public void argumentCapturing() { 387 | 388 | //SUT 389 | mock.add("SomeString"); 390 | 391 | //Verification 392 | ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); 393 | verify(mock).add(captor.capture()); 394 | 395 | assertEquals("SomeString", captor.getValue()); 396 | 397 | } 398 | 399 | @Test 400 | public void multipleArgumentCapturing() { 401 | 402 | //SUT 403 | mock.add("SomeString1"); 404 | mock.add("SomeString2"); 405 | 406 | //Verification 407 | ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); 408 | 409 | verify(mock, times(2)).add(captor.capture()); 410 | 411 | List allValues = captor.getAllValues(); 412 | 413 | assertEquals("SomeString1", allValues.get(0)); 414 | assertEquals("SomeString2", allValues.get(1)); 415 | 416 | } 417 | 418 | @Test 419 | public void mocking() { 420 | ArrayList arrayListMock = mock(ArrayList.class); 421 | System.out.println(arrayListMock.get(0));//null 422 | System.out.println(arrayListMock.size());//0 423 | arrayListMock.add("Test"); 424 | arrayListMock.add("Test2"); 425 | System.out.println(arrayListMock.size());//0 426 | when(arrayListMock.size()).thenReturn(5); 427 | System.out.println(arrayListMock.size());//5 428 | } 429 | 430 | @Test 431 | public void spying() { 432 | ArrayList arrayListSpy = spy(ArrayList.class); 433 | arrayListSpy.add("Test0"); 434 | System.out.println(arrayListSpy.get(0));//Test0 435 | System.out.println(arrayListSpy.size());//1 436 | arrayListSpy.add("Test"); 437 | arrayListSpy.add("Test2"); 438 | System.out.println(arrayListSpy.size());//3 439 | 440 | when(arrayListSpy.size()).thenReturn(5); 441 | System.out.println(arrayListSpy.size());//5 442 | 443 | arrayListSpy.add("Test4"); 444 | System.out.println(arrayListSpy.size());//5 445 | 446 | verify(arrayListSpy).add("Test4"); 447 | } 448 | 449 | 450 | } 451 | ``` 452 | --- 453 | 454 | ### /src/test/java/com/in28minutes/unittesting/unittesting/business/SomeBusinessMockTest.java 455 | 456 | ```java 457 | package com.in28minutes.unittesting.unittesting.business; 458 | 459 | import static org.junit.Assert.assertEquals; 460 | import static org.mockito.Mockito.when; 461 | 462 | import org.junit.Test; 463 | import org.junit.runner.RunWith; 464 | import org.mockito.InjectMocks; 465 | import org.mockito.Mock; 466 | import org.mockito.junit.MockitoJUnitRunner; 467 | 468 | import com.in28minutes.unittesting.unittesting.data.SomeDataService; 469 | 470 | @RunWith(MockitoJUnitRunner.class) 471 | public class SomeBusinessMockTest { 472 | 473 | @InjectMocks 474 | SomeBusinessImpl business; 475 | 476 | @Mock 477 | SomeDataService dataServiceMock; 478 | 479 | @Test 480 | public void calculateSumUsingDataService_basic() { 481 | when(dataServiceMock.retrieveAllData()).thenReturn(new int[] { 1, 2, 3 }); 482 | assertEquals(6, business.calculateSumUsingDataService()); 483 | } 484 | 485 | @Test 486 | public void calculateSumUsingDataService_empty() { 487 | when(dataServiceMock.retrieveAllData()).thenReturn(new int[] {}); 488 | assertEquals(0, business.calculateSumUsingDataService()); 489 | } 490 | 491 | @Test 492 | public void calculateSumUsingDataService_oneValue() { 493 | when(dataServiceMock.retrieveAllData()).thenReturn(new int[] { 5 }); 494 | assertEquals(5, business.calculateSumUsingDataService()); 495 | } 496 | } 497 | ``` 498 | --- 499 | 500 | ### /src/test/java/com/in28minutes/unittesting/unittesting/business/SomeBusinessStubTest.java 501 | 502 | ```java 503 | package com.in28minutes.unittesting.unittesting.business; 504 | 505 | import static org.junit.Assert.assertEquals; 506 | 507 | import org.junit.Test; 508 | 509 | import com.in28minutes.unittesting.unittesting.data.SomeDataService; 510 | 511 | class SomeDataServiceStub implements SomeDataService { 512 | @Override 513 | public int[] retrieveAllData() { 514 | return new int[] { 1, 2, 3 }; 515 | } 516 | } 517 | 518 | class SomeDataServiceEmptyStub implements SomeDataService { 519 | @Override 520 | public int[] retrieveAllData() { 521 | return new int[] { }; 522 | } 523 | } 524 | 525 | class SomeDataServiceOneElementStub implements SomeDataService { 526 | @Override 527 | public int[] retrieveAllData() { 528 | return new int[] { 5 }; 529 | } 530 | } 531 | 532 | public class SomeBusinessStubTest { 533 | 534 | @Test 535 | public void calculateSumUsingDataService_basic() { 536 | SomeBusinessImpl business = new SomeBusinessImpl(); 537 | business.setSomeDataService(new SomeDataServiceStub()); 538 | int actualResult = business.calculateSumUsingDataService(); 539 | int expectedResult = 6; 540 | assertEquals(expectedResult, actualResult); 541 | } 542 | 543 | @Test 544 | public void calculateSumUsingDataService_empty() { 545 | SomeBusinessImpl business = new SomeBusinessImpl(); 546 | business.setSomeDataService(new SomeDataServiceEmptyStub()); 547 | int actualResult = business.calculateSumUsingDataService();//new int[] {} 548 | int expectedResult = 0; 549 | assertEquals(expectedResult, actualResult); 550 | } 551 | 552 | @Test 553 | public void calculateSumUsingDataService_oneValue() { 554 | SomeBusinessImpl business = new SomeBusinessImpl(); 555 | business.setSomeDataService(new SomeDataServiceOneElementStub()); 556 | int actualResult = business.calculateSumUsingDataService();//new int[] { 5 } 557 | int expectedResult = 5; 558 | assertEquals(expectedResult, actualResult); 559 | } 560 | } 561 | ``` 562 | --- 563 | 564 | ### /src/test/java/com/in28minutes/unittesting/unittesting/business/SomeBusinessTest.java 565 | 566 | ```java 567 | package com.in28minutes.unittesting.unittesting.business; 568 | 569 | import static org.junit.Assert.*; 570 | 571 | import org.junit.Test; 572 | 573 | public class SomeBusinessTest { 574 | 575 | @Test 576 | public void calculateSum_basic() { 577 | SomeBusinessImpl business = new SomeBusinessImpl(); 578 | int actualResult = business.calculateSum(new int[] { 1,2,3}); 579 | int expectedResult = 6; 580 | assertEquals(expectedResult, actualResult); 581 | } 582 | 583 | @Test 584 | public void calculateSum_empty() { 585 | SomeBusinessImpl business = new SomeBusinessImpl(); 586 | int actualResult = business.calculateSum(new int[] { }); 587 | int expectedResult = 0; 588 | assertEquals(expectedResult, actualResult); 589 | } 590 | 591 | @Test 592 | public void calculateSum_oneValue() { 593 | SomeBusinessImpl business = new SomeBusinessImpl(); 594 | int actualResult = business.calculateSum(new int[] { 5}); 595 | int expectedResult = 5; 596 | assertEquals(expectedResult, actualResult); 597 | } 598 | } 599 | ``` 600 | --- 601 | 602 | ### /src/test/java/com/in28minutes/unittesting/unittesting/controller/HelloWorldControllerTest.java 603 | 604 | ```java 605 | package com.in28minutes.unittesting.unittesting.controller; 606 | 607 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 608 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 609 | 610 | import org.junit.Test; 611 | import org.junit.runner.RunWith; 612 | import org.springframework.beans.factory.annotation.Autowired; 613 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 614 | import org.springframework.http.MediaType; 615 | import org.springframework.test.context.junit4.SpringRunner; 616 | import org.springframework.test.web.servlet.MockMvc; 617 | import org.springframework.test.web.servlet.MvcResult; 618 | import org.springframework.test.web.servlet.RequestBuilder; 619 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; 620 | 621 | @RunWith(SpringRunner.class) 622 | @WebMvcTest(HelloWorldController.class) 623 | public class HelloWorldControllerTest { 624 | 625 | @Autowired 626 | private MockMvc mockMvc; 627 | 628 | @Test 629 | public void helloWorld_basic() throws Exception { 630 | //call GET "/hello-world" application/json 631 | 632 | RequestBuilder request = MockMvcRequestBuilders 633 | .get("/hello-world") 634 | .accept(MediaType.APPLICATION_JSON); 635 | 636 | MvcResult result = mockMvc.perform(request) 637 | .andExpect(status().isOk()) 638 | .andExpect(content().string("Hello World")) 639 | .andReturn(); 640 | 641 | //verify "Hello World" 642 | //assertEquals("Hello World", result.getResponse().getContentAsString()); 643 | } 644 | 645 | } 646 | ``` 647 | --- 648 | 649 | ### /src/test/java/com/in28minutes/unittesting/unittesting/controller/ItemControllerIT.java 650 | 651 | ```java 652 | package com.in28minutes.unittesting.unittesting.controller; 653 | 654 | import org.json.JSONException; 655 | import org.junit.Test; 656 | import org.junit.runner.RunWith; 657 | import org.skyscreamer.jsonassert.JSONAssert; 658 | import org.springframework.beans.factory.annotation.Autowired; 659 | import org.springframework.boot.test.context.SpringBootTest; 660 | import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; 661 | import org.springframework.boot.test.web.client.TestRestTemplate; 662 | import org.springframework.test.context.junit4.SpringRunner; 663 | 664 | @RunWith(SpringRunner.class) 665 | @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT) 666 | public class ItemControllerIT { 667 | 668 | @Autowired 669 | private TestRestTemplate restTemplate; 670 | 671 | @Test 672 | public void contextLoads() throws JSONException { 673 | 674 | String response = this.restTemplate.getForObject("/all-items-from-database", String.class); 675 | 676 | JSONAssert.assertEquals("[{id:10001},{id:10002},{id:10003}]", 677 | response, false); 678 | } 679 | 680 | } 681 | ``` 682 | --- 683 | 684 | ### /src/test/java/com/in28minutes/unittesting/unittesting/controller/ItemControllerTest.java 685 | 686 | ```java 687 | package com.in28minutes.unittesting.unittesting.controller; 688 | 689 | import static org.mockito.Mockito.when; 690 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 691 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 692 | 693 | import java.util.Arrays; 694 | 695 | import org.junit.Test; 696 | import org.junit.runner.RunWith; 697 | import org.springframework.beans.factory.annotation.Autowired; 698 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 699 | import org.springframework.boot.test.mock.mockito.MockBean; 700 | import org.springframework.http.MediaType; 701 | import org.springframework.test.context.junit4.SpringRunner; 702 | import org.springframework.test.web.servlet.MockMvc; 703 | import org.springframework.test.web.servlet.MvcResult; 704 | import org.springframework.test.web.servlet.RequestBuilder; 705 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; 706 | 707 | import com.in28minutes.unittesting.unittesting.business.ItemBusinessService; 708 | import com.in28minutes.unittesting.unittesting.model.Item; 709 | 710 | @RunWith(SpringRunner.class) 711 | @WebMvcTest(ItemController.class) 712 | public class ItemControllerTest { 713 | 714 | @Autowired 715 | private MockMvc mockMvc; 716 | 717 | @MockBean 718 | private ItemBusinessService businessService; 719 | 720 | @Test 721 | public void dummyItem_basic() throws Exception { 722 | 723 | RequestBuilder request = MockMvcRequestBuilders 724 | .get("/dummy-item") 725 | .accept(MediaType.APPLICATION_JSON); 726 | 727 | MvcResult result = mockMvc.perform(request) 728 | .andExpect(status().isOk()) 729 | .andExpect(content().json("{\"id\": 1,\"name\":\"Ball\",\"price\":10,\"quantity\":100}")) 730 | .andReturn(); 731 | //JSONAssert.assertEquals(expected, result.getResponse().getContentAsString(), false); 732 | 733 | } 734 | 735 | @Test 736 | public void itemFromBusinessService_basic() throws Exception { 737 | when(businessService.retreiveHardcodedItem()).thenReturn( 738 | new Item(2,"Item2",10,10)); 739 | 740 | RequestBuilder request = MockMvcRequestBuilders 741 | .get("/item-from-business-service") 742 | .accept(MediaType.APPLICATION_JSON); 743 | 744 | MvcResult result = mockMvc.perform(request) 745 | .andExpect(status().isOk()) 746 | .andExpect(content().json("{id:2,name:Item2,price:10}")) 747 | .andReturn(); 748 | //JSONAssert.assertEquals(expected, result.getResponse().getContentAsString(), false); 749 | 750 | } 751 | 752 | @Test 753 | public void retrieveAllItems_basic() throws Exception { 754 | when(businessService.retrieveAllItems()).thenReturn( 755 | Arrays.asList(new Item(2,"Item2",10,10), 756 | new Item(3,"Item3",20,20)) 757 | ); 758 | 759 | RequestBuilder request = MockMvcRequestBuilders 760 | .get("/all-items-from-database") 761 | .accept(MediaType.APPLICATION_JSON); 762 | 763 | MvcResult result = mockMvc.perform(request) 764 | .andExpect(status().isOk()) 765 | .andExpect(content().json("[{id:3,name:Item3,price:20}, {id:2,name:Item2,price:10}]")) 766 | .andReturn(); 767 | //JSONAssert.assertEquals(expected, result.getResponse().getContentAsString(), false); 768 | 769 | } 770 | 771 | } 772 | ``` 773 | --- 774 | 775 | ### /src/test/java/com/in28minutes/unittesting/unittesting/data/ItemRepositoryTest.java 776 | 777 | ```java 778 | package com.in28minutes.unittesting.unittesting.data; 779 | 780 | import static org.junit.Assert.assertEquals; 781 | 782 | import java.util.List; 783 | 784 | import org.junit.Test; 785 | import org.junit.runner.RunWith; 786 | import org.springframework.beans.factory.annotation.Autowired; 787 | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; 788 | import org.springframework.test.context.junit4.SpringRunner; 789 | 790 | import com.in28minutes.unittesting.unittesting.model.Item; 791 | 792 | @RunWith(SpringRunner.class) 793 | @DataJpaTest 794 | public class ItemRepositoryTest { 795 | 796 | @Autowired 797 | private ItemRepository repository; 798 | 799 | @Test 800 | public void testFindAll() { 801 | List items = repository.findAll(); 802 | assertEquals(3,items.size()); 803 | } 804 | 805 | } 806 | ``` 807 | --- 808 | 809 | ### /src/test/java/com/in28minutes/unittesting/unittesting/spike/JsonAssertTest.java 810 | 811 | ```java 812 | package com.in28minutes.unittesting.unittesting.spike; 813 | 814 | import org.json.JSONException; 815 | import org.junit.Test; 816 | import org.skyscreamer.jsonassert.JSONAssert; 817 | 818 | public class JsonAssertTest { 819 | 820 | String actualResponse = "{\"id\":1,\"name\":\"Ball\",\"price\":10,\"quantity\":100}"; 821 | 822 | @Test 823 | public void jsonAssert_StrictTrue_ExactMatchExceptForSpaces() throws JSONException { 824 | String expectedResponse = "{\"id\": 1, \"name\":\"Ball\", \"price\":10, \"quantity\":100}"; 825 | JSONAssert.assertEquals(expectedResponse, actualResponse, true); 826 | } 827 | 828 | @Test 829 | public void jsonAssert_StrictFalse() throws JSONException { 830 | String expectedResponse = "{\"id\": 1, \"name\":\"Ball\", \"price\":10}"; 831 | JSONAssert.assertEquals(expectedResponse, actualResponse, false); 832 | } 833 | 834 | @Test 835 | public void jsonAssert_WithoutEscapeCharacters() throws JSONException { 836 | String expectedResponse = "{id:1, name:Ball, price:10}"; 837 | JSONAssert.assertEquals(expectedResponse, actualResponse, false); 838 | } 839 | } 840 | ``` 841 | --- 842 | 843 | ### /src/test/java/com/in28minutes/unittesting/unittesting/UnitTestingApplicationTests.java 844 | 845 | ```java 846 | package com.in28minutes.unittesting.unittesting; 847 | 848 | import org.junit.Test; 849 | import org.junit.runner.RunWith; 850 | import org.springframework.boot.test.context.SpringBootTest; 851 | import org.springframework.test.context.junit4.SpringRunner; 852 | 853 | @RunWith(SpringRunner.class) 854 | @SpringBootTest 855 | public class UnitTestingApplicationTests { 856 | 857 | @Test 858 | public void contextLoads() { 859 | } 860 | 861 | } 862 | ``` 863 | --- 864 | -------------------------------------------------------------------------------- /02.Final.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | ## Complete Code Example 6 | 7 | 8 | ### /src/main/java/com/in28minutes/unittesting/unittesting/business/ItemBusinessService.java 9 | 10 | ```java 11 | package com.in28minutes.unittesting.unittesting.business; 12 | 13 | import java.util.List; 14 | 15 | import org.springframework.beans.factory.annotation.Autowired; 16 | import org.springframework.stereotype.Component; 17 | 18 | import com.in28minutes.unittesting.unittesting.data.ItemRepository; 19 | import com.in28minutes.unittesting.unittesting.model.Item; 20 | 21 | @Component 22 | public class ItemBusinessService { 23 | 24 | @Autowired 25 | private ItemRepository repository; 26 | 27 | public Item retreiveHardcodedItem() { 28 | return new Item(1, "Ball", 10, 100); 29 | } 30 | 31 | public List retrieveAllItems() { 32 | List items = repository.findAll(); 33 | 34 | for(Item item:items) { 35 | item.setValue(item.getPrice() * item.getQuantity()); 36 | } 37 | 38 | return items; 39 | } 40 | 41 | } 42 | ``` 43 | --- 44 | 45 | ### /src/main/java/com/in28minutes/unittesting/unittesting/business/SomeBusinessImpl.java 46 | 47 | ```java 48 | package com.in28minutes.unittesting.unittesting.business; 49 | 50 | import com.in28minutes.unittesting.unittesting.data.SomeDataService; 51 | 52 | public class SomeBusinessImpl { 53 | 54 | private SomeDataService someDataService; 55 | 56 | public void setSomeDataService(SomeDataService someDataService) { 57 | this.someDataService = someDataService; 58 | } 59 | 60 | public int calculateSum(int[] data) { 61 | int sum = 0; 62 | for(int value:data) { 63 | sum += value; 64 | } 65 | return sum; 66 | //Functional Style 67 | //return Arrays.stream(data).reduce(Integer::sum).orElse(0); 68 | } 69 | 70 | public int calculateSumUsingDataService() { 71 | int sum = 0; 72 | int[] data = someDataService.retrieveAllData(); 73 | for(int value:data) { 74 | sum += value; 75 | } 76 | 77 | //someDataService.storeSum(sum); 78 | return sum; 79 | //Functional Style 80 | //return Arrays.stream(data).reduce(Integer::sum).orElse(0); 81 | } 82 | 83 | } 84 | ``` 85 | --- 86 | 87 | ### /src/main/java/com/in28minutes/unittesting/unittesting/controller/HelloWorldController.java 88 | 89 | ```java 90 | package com.in28minutes.unittesting.unittesting.controller; 91 | 92 | import org.springframework.web.bind.annotation.GetMapping; 93 | import org.springframework.web.bind.annotation.RestController; 94 | 95 | @RestController 96 | public class HelloWorldController { 97 | 98 | @GetMapping("/hello-world") 99 | public String helloWorld() { 100 | return "Hello World"; 101 | } 102 | 103 | } 104 | ``` 105 | --- 106 | 107 | ### /src/main/java/com/in28minutes/unittesting/unittesting/controller/ItemController.java 108 | 109 | ```java 110 | package com.in28minutes.unittesting.unittesting.controller; 111 | 112 | import java.util.List; 113 | 114 | import org.springframework.beans.factory.annotation.Autowired; 115 | import org.springframework.web.bind.annotation.GetMapping; 116 | import org.springframework.web.bind.annotation.RestController; 117 | 118 | import com.in28minutes.unittesting.unittesting.business.ItemBusinessService; 119 | import com.in28minutes.unittesting.unittesting.model.Item; 120 | 121 | @RestController 122 | public class ItemController { 123 | 124 | @Autowired 125 | private ItemBusinessService businessService; 126 | 127 | @GetMapping("/dummy-item") 128 | public Item dummyItem() { 129 | return new Item(1, "Ball", 10, 100); 130 | } 131 | 132 | @GetMapping("/item-from-business-service") 133 | public Item itemFromBusinessService() { 134 | Item item = businessService.retreiveHardcodedItem(); 135 | 136 | return item; 137 | } 138 | 139 | @GetMapping("/all-items-from-database") 140 | public List retrieveAllItems() { 141 | return businessService.retrieveAllItems(); 142 | } 143 | 144 | } 145 | ``` 146 | --- 147 | 148 | ### /src/main/java/com/in28minutes/unittesting/unittesting/data/ItemRepository.java 149 | 150 | ```java 151 | package com.in28minutes.unittesting.unittesting.data; 152 | 153 | import org.springframework.data.jpa.repository.JpaRepository; 154 | 155 | import com.in28minutes.unittesting.unittesting.model.Item; 156 | 157 | public interface ItemRepository extends JpaRepository{ 158 | 159 | } 160 | ``` 161 | --- 162 | 163 | ### /src/main/java/com/in28minutes/unittesting/unittesting/data/SomeDataService.java 164 | 165 | ```java 166 | package com.in28minutes.unittesting.unittesting.data; 167 | 168 | public interface SomeDataService { 169 | 170 | int[] retrieveAllData(); 171 | 172 | //int retrieveSpecificData(); 173 | 174 | } 175 | ``` 176 | --- 177 | 178 | ### /src/main/java/com/in28minutes/unittesting/unittesting/model/Item.java 179 | 180 | ```java 181 | package com.in28minutes.unittesting.unittesting.model; 182 | 183 | import javax.persistence.Entity; 184 | import javax.persistence.Id; 185 | import javax.persistence.Transient; 186 | 187 | @Entity 188 | public class Item { 189 | 190 | @Id 191 | private int id; 192 | private String name; 193 | private int price; 194 | private int quantity; 195 | 196 | @Transient 197 | private int value; 198 | 199 | protected Item() { 200 | 201 | } 202 | 203 | public Item(int id, String name, int price, int quantity) { 204 | this.id = id; 205 | this.name = name; 206 | this.price = price; 207 | this.quantity = quantity; 208 | } 209 | 210 | public int getId() { 211 | return id; 212 | } 213 | 214 | public String getName() { 215 | return name; 216 | } 217 | 218 | public int getPrice() { 219 | return price; 220 | } 221 | 222 | public int getQuantity() { 223 | return quantity; 224 | } 225 | 226 | public int getValue() { 227 | return value; 228 | } 229 | 230 | public void setValue(int value) { 231 | this.value = value; 232 | } 233 | 234 | public String toString() { 235 | return String.format("Item[%d, %s, %d, %d]", id, name, price, quantity); 236 | } 237 | } 238 | ``` 239 | --- 240 | 241 | ### /src/main/java/com/in28minutes/unittesting/unittesting/UnitTestingApplication.java 242 | 243 | ```java 244 | package com.in28minutes.unittesting.unittesting; 245 | 246 | import org.springframework.boot.SpringApplication; 247 | import org.springframework.boot.autoconfigure.SpringBootApplication; 248 | 249 | @SpringBootApplication 250 | public class UnitTestingApplication { 251 | 252 | public static void main(String[] args) { 253 | SpringApplication.run(UnitTestingApplication.class, args); 254 | } 255 | } 256 | ``` 257 | --- 258 | 259 | ### /src/main/resources/application.properties 260 | 261 | ```properties 262 | spring.jpa.show-sql=true 263 | spring.h2.console.enabled=true 264 | ``` 265 | --- 266 | 267 | ### /src/main/resources/data.sql 268 | 269 | ``` 270 | insert into item(id, name, price, quantity) values(10001,'Item1',10,20); 271 | insert into item(id, name, price, quantity) values(10002,'Item2',5,10); 272 | insert into item(id, name, price, quantity) values(10003,'Item3',15,2); 273 | ``` 274 | --- 275 | 276 | ### /src/test/java/com/in28minutes/unittesting/unittesting/business/ItemBusinessServiceTest.java 277 | 278 | ```java 279 | package com.in28minutes.unittesting.unittesting.business; 280 | 281 | import static org.junit.Assert.assertEquals; 282 | import static org.mockito.Mockito.when; 283 | 284 | import java.util.Arrays; 285 | import java.util.List; 286 | 287 | import org.junit.Test; 288 | import org.junit.runner.RunWith; 289 | import org.mockito.InjectMocks; 290 | import org.mockito.Mock; 291 | import org.mockito.junit.MockitoJUnitRunner; 292 | 293 | import com.in28minutes.unittesting.unittesting.data.ItemRepository; 294 | import com.in28minutes.unittesting.unittesting.model.Item; 295 | 296 | @RunWith(MockitoJUnitRunner.class) 297 | public class ItemBusinessServiceTest { 298 | 299 | @InjectMocks 300 | private ItemBusinessService business; 301 | 302 | @Mock 303 | private ItemRepository repository; 304 | 305 | @Test 306 | public void retrieveAllItems_basic() { 307 | when(repository.findAll()).thenReturn(Arrays.asList(new Item(2,"Item2",10,10), 308 | new Item(3,"Item3",20,20))); 309 | List items = business.retrieveAllItems(); 310 | 311 | assertEquals(100, items.get(0).getValue()); 312 | assertEquals(400, items.get(1).getValue()); 313 | } 314 | } 315 | ``` 316 | --- 317 | 318 | ### /src/test/java/com/in28minutes/unittesting/unittesting/business/ListMockTest.java 319 | 320 | ```java 321 | package com.in28minutes.unittesting.unittesting.business; 322 | 323 | import static org.junit.Assert.assertEquals; 324 | import static org.mockito.ArgumentMatchers.anyInt; 325 | import static org.mockito.Mockito.atLeast; 326 | import static org.mockito.Mockito.atLeastOnce; 327 | import static org.mockito.Mockito.atMost; 328 | import static org.mockito.Mockito.mock; 329 | import static org.mockito.Mockito.never; 330 | import static org.mockito.Mockito.spy; 331 | import static org.mockito.Mockito.times; 332 | import static org.mockito.Mockito.verify; 333 | import static org.mockito.Mockito.when; 334 | 335 | import java.util.ArrayList; 336 | import java.util.List; 337 | 338 | import org.junit.Ignore; 339 | import org.junit.Test; 340 | import org.mockito.ArgumentCaptor; 341 | 342 | public class ListMockTest { 343 | 344 | List mock = mock(List.class); 345 | 346 | @Test 347 | public void size_basic() { 348 | when(mock.size()).thenReturn(5); 349 | assertEquals(5, mock.size()); 350 | } 351 | 352 | @Test 353 | public void returnDifferentValues() { 354 | when(mock.size()).thenReturn(5).thenReturn(10); 355 | assertEquals(5, mock.size()); 356 | assertEquals(10, mock.size()); 357 | } 358 | 359 | @Test 360 | @Ignore 361 | public void returnWithParameters() { 362 | when(mock.get(0)).thenReturn("in28Minutes"); 363 | assertEquals("in28Minutes", mock.get(0)); 364 | assertEquals(null, mock.get(1)); 365 | } 366 | 367 | @Test 368 | public void returnWithGenericParameters() { 369 | when(mock.get(anyInt())).thenReturn("in28Minutes"); 370 | 371 | assertEquals("in28Minutes", mock.get(0)); 372 | assertEquals("in28Minutes", mock.get(1)); 373 | } 374 | 375 | @Test 376 | public void verificationBasics() { 377 | // SUT 378 | String value1 = mock.get(0); 379 | String value2 = mock.get(1); 380 | 381 | // Verify 382 | verify(mock).get(0); 383 | verify(mock, times(2)).get(anyInt()); 384 | verify(mock, atLeast(1)).get(anyInt()); 385 | verify(mock, atLeastOnce()).get(anyInt()); 386 | verify(mock, atMost(2)).get(anyInt()); 387 | verify(mock, never()).get(2); 388 | } 389 | 390 | @Test 391 | public void argumentCapturing() { 392 | 393 | //SUT 394 | mock.add("SomeString"); 395 | 396 | //Verification 397 | ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); 398 | verify(mock).add(captor.capture()); 399 | 400 | assertEquals("SomeString", captor.getValue()); 401 | 402 | } 403 | 404 | @Test 405 | public void multipleArgumentCapturing() { 406 | 407 | //SUT 408 | mock.add("SomeString1"); 409 | mock.add("SomeString2"); 410 | 411 | //Verification 412 | ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); 413 | 414 | verify(mock, times(2)).add(captor.capture()); 415 | 416 | List allValues = captor.getAllValues(); 417 | 418 | assertEquals("SomeString1", allValues.get(0)); 419 | assertEquals("SomeString2", allValues.get(1)); 420 | 421 | } 422 | 423 | @Test 424 | public void mocking() { 425 | ArrayList arrayListMock = mock(ArrayList.class); 426 | System.out.println(arrayListMock.get(0));//null 427 | System.out.println(arrayListMock.size());//0 428 | arrayListMock.add("Test"); 429 | arrayListMock.add("Test2"); 430 | System.out.println(arrayListMock.size());//0 431 | when(arrayListMock.size()).thenReturn(5); 432 | System.out.println(arrayListMock.size());//5 433 | } 434 | 435 | @Test 436 | public void spying() { 437 | ArrayList arrayListSpy = spy(ArrayList.class); 438 | arrayListSpy.add("Test0"); 439 | System.out.println(arrayListSpy.get(0));//Test0 440 | System.out.println(arrayListSpy.size());//1 441 | arrayListSpy.add("Test"); 442 | arrayListSpy.add("Test2"); 443 | System.out.println(arrayListSpy.size());//3 444 | 445 | when(arrayListSpy.size()).thenReturn(5); 446 | System.out.println(arrayListSpy.size());//5 447 | 448 | arrayListSpy.add("Test4"); 449 | System.out.println(arrayListSpy.size());//5 450 | 451 | verify(arrayListSpy).add("Test4"); 452 | } 453 | 454 | 455 | } 456 | ``` 457 | --- 458 | 459 | ### /src/test/java/com/in28minutes/unittesting/unittesting/business/SomeBusinessMockTest.java 460 | 461 | ```java 462 | package com.in28minutes.unittesting.unittesting.business; 463 | 464 | import static org.junit.Assert.assertEquals; 465 | import static org.mockito.Mockito.when; 466 | 467 | import org.junit.Test; 468 | import org.junit.runner.RunWith; 469 | import org.mockito.InjectMocks; 470 | import org.mockito.Mock; 471 | import org.mockito.junit.MockitoJUnitRunner; 472 | 473 | import com.in28minutes.unittesting.unittesting.data.SomeDataService; 474 | 475 | @RunWith(MockitoJUnitRunner.class) 476 | public class SomeBusinessMockTest { 477 | 478 | @InjectMocks 479 | SomeBusinessImpl business; 480 | 481 | @Mock 482 | SomeDataService dataServiceMock; 483 | 484 | @Test 485 | public void calculateSumUsingDataService_basic() { 486 | when(dataServiceMock.retrieveAllData()).thenReturn(new int[] { 1, 2, 3 }); 487 | assertEquals(6, business.calculateSumUsingDataService()); 488 | } 489 | 490 | @Test 491 | public void calculateSumUsingDataService_empty() { 492 | when(dataServiceMock.retrieveAllData()).thenReturn(new int[] {}); 493 | assertEquals(0, business.calculateSumUsingDataService()); 494 | } 495 | 496 | @Test 497 | public void calculateSumUsingDataService_oneValue() { 498 | when(dataServiceMock.retrieveAllData()).thenReturn(new int[] { 5 }); 499 | assertEquals(5, business.calculateSumUsingDataService()); 500 | } 501 | } 502 | ``` 503 | --- 504 | 505 | ### /src/test/java/com/in28minutes/unittesting/unittesting/business/SomeBusinessStubTest.java 506 | 507 | ```java 508 | package com.in28minutes.unittesting.unittesting.business; 509 | 510 | import static org.junit.Assert.assertEquals; 511 | 512 | import org.junit.Test; 513 | 514 | import com.in28minutes.unittesting.unittesting.data.SomeDataService; 515 | 516 | class SomeDataServiceStub implements SomeDataService { 517 | @Override 518 | public int[] retrieveAllData() { 519 | return new int[] { 1, 2, 3 }; 520 | } 521 | } 522 | 523 | class SomeDataServiceEmptyStub implements SomeDataService { 524 | @Override 525 | public int[] retrieveAllData() { 526 | return new int[] { }; 527 | } 528 | } 529 | 530 | class SomeDataServiceOneElementStub implements SomeDataService { 531 | @Override 532 | public int[] retrieveAllData() { 533 | return new int[] { 5 }; 534 | } 535 | } 536 | 537 | public class SomeBusinessStubTest { 538 | 539 | @Test 540 | public void calculateSumUsingDataService_basic() { 541 | SomeBusinessImpl business = new SomeBusinessImpl(); 542 | business.setSomeDataService(new SomeDataServiceStub()); 543 | int actualResult = business.calculateSumUsingDataService(); 544 | int expectedResult = 6; 545 | assertEquals(expectedResult, actualResult); 546 | } 547 | 548 | @Test 549 | public void calculateSumUsingDataService_empty() { 550 | SomeBusinessImpl business = new SomeBusinessImpl(); 551 | business.setSomeDataService(new SomeDataServiceEmptyStub()); 552 | int actualResult = business.calculateSumUsingDataService();//new int[] {} 553 | int expectedResult = 0; 554 | assertEquals(expectedResult, actualResult); 555 | } 556 | 557 | @Test 558 | public void calculateSumUsingDataService_oneValue() { 559 | SomeBusinessImpl business = new SomeBusinessImpl(); 560 | business.setSomeDataService(new SomeDataServiceOneElementStub()); 561 | int actualResult = business.calculateSumUsingDataService();//new int[] { 5 } 562 | int expectedResult = 5; 563 | assertEquals(expectedResult, actualResult); 564 | } 565 | } 566 | ``` 567 | --- 568 | 569 | ### /src/test/java/com/in28minutes/unittesting/unittesting/business/SomeBusinessTest.java 570 | 571 | ```java 572 | package com.in28minutes.unittesting.unittesting.business; 573 | 574 | import static org.junit.Assert.*; 575 | 576 | import org.junit.Test; 577 | 578 | public class SomeBusinessTest { 579 | 580 | @Test 581 | public void calculateSum_basic() { 582 | SomeBusinessImpl business = new SomeBusinessImpl(); 583 | int actualResult = business.calculateSum(new int[] { 1,2,3}); 584 | int expectedResult = 6; 585 | assertEquals(expectedResult, actualResult); 586 | } 587 | 588 | @Test 589 | public void calculateSum_empty() { 590 | SomeBusinessImpl business = new SomeBusinessImpl(); 591 | int actualResult = business.calculateSum(new int[] { }); 592 | int expectedResult = 0; 593 | assertEquals(expectedResult, actualResult); 594 | } 595 | 596 | @Test 597 | public void calculateSum_oneValue() { 598 | SomeBusinessImpl business = new SomeBusinessImpl(); 599 | int actualResult = business.calculateSum(new int[] { 5}); 600 | int expectedResult = 5; 601 | assertEquals(expectedResult, actualResult); 602 | } 603 | } 604 | ``` 605 | --- 606 | 607 | ### /src/test/java/com/in28minutes/unittesting/unittesting/controller/HelloWorldControllerTest.java 608 | 609 | ```java 610 | package com.in28minutes.unittesting.unittesting.controller; 611 | 612 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 613 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 614 | 615 | import org.junit.Test; 616 | import org.junit.runner.RunWith; 617 | import org.springframework.beans.factory.annotation.Autowired; 618 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 619 | import org.springframework.http.MediaType; 620 | import org.springframework.test.context.junit4.SpringRunner; 621 | import org.springframework.test.web.servlet.MockMvc; 622 | import org.springframework.test.web.servlet.MvcResult; 623 | import org.springframework.test.web.servlet.RequestBuilder; 624 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; 625 | 626 | @RunWith(SpringRunner.class) 627 | @WebMvcTest(HelloWorldController.class) 628 | public class HelloWorldControllerTest { 629 | 630 | @Autowired 631 | private MockMvc mockMvc; 632 | 633 | @Test 634 | public void helloWorld_basic() throws Exception { 635 | //call GET "/hello-world" application/json 636 | 637 | RequestBuilder request = MockMvcRequestBuilders 638 | .get("/hello-world") 639 | .accept(MediaType.APPLICATION_JSON); 640 | 641 | MvcResult result = mockMvc.perform(request) 642 | .andExpect(status().isOk()) 643 | .andExpect(content().string("Hello World")) 644 | .andReturn(); 645 | 646 | //verify "Hello World" 647 | //assertEquals("Hello World", result.getResponse().getContentAsString()); 648 | } 649 | 650 | } 651 | ``` 652 | --- 653 | 654 | ### /src/test/java/com/in28minutes/unittesting/unittesting/controller/ItemControllerIT.java 655 | 656 | ```java 657 | package com.in28minutes.unittesting.unittesting.controller; 658 | 659 | import org.json.JSONException; 660 | import org.junit.Test; 661 | import org.junit.runner.RunWith; 662 | import org.skyscreamer.jsonassert.JSONAssert; 663 | import org.springframework.beans.factory.annotation.Autowired; 664 | import org.springframework.boot.test.context.SpringBootTest; 665 | import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; 666 | import org.springframework.boot.test.web.client.TestRestTemplate; 667 | import org.springframework.test.context.junit4.SpringRunner; 668 | 669 | @RunWith(SpringRunner.class) 670 | @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT) 671 | public class ItemControllerIT { 672 | 673 | @Autowired 674 | private TestRestTemplate restTemplate; 675 | 676 | @Test 677 | public void contextLoads() throws JSONException { 678 | 679 | String response = this.restTemplate.getForObject("/all-items-from-database", String.class); 680 | 681 | JSONAssert.assertEquals("[{id:10001},{id:10002},{id:10003}]", 682 | response, false); 683 | } 684 | 685 | } 686 | ``` 687 | --- 688 | 689 | ### /src/test/java/com/in28minutes/unittesting/unittesting/controller/ItemControllerTest.java 690 | 691 | ```java 692 | package com.in28minutes.unittesting.unittesting.controller; 693 | 694 | import static org.mockito.Mockito.when; 695 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 696 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 697 | 698 | import java.util.Arrays; 699 | 700 | import org.junit.Test; 701 | import org.junit.runner.RunWith; 702 | import org.springframework.beans.factory.annotation.Autowired; 703 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 704 | import org.springframework.boot.test.mock.mockito.MockBean; 705 | import org.springframework.http.MediaType; 706 | import org.springframework.test.context.junit4.SpringRunner; 707 | import org.springframework.test.web.servlet.MockMvc; 708 | import org.springframework.test.web.servlet.MvcResult; 709 | import org.springframework.test.web.servlet.RequestBuilder; 710 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; 711 | 712 | import com.in28minutes.unittesting.unittesting.business.ItemBusinessService; 713 | import com.in28minutes.unittesting.unittesting.model.Item; 714 | 715 | @RunWith(SpringRunner.class) 716 | @WebMvcTest(ItemController.class) 717 | public class ItemControllerTest { 718 | 719 | @Autowired 720 | private MockMvc mockMvc; 721 | 722 | @MockBean 723 | private ItemBusinessService businessService; 724 | 725 | @Test 726 | public void dummyItem_basic() throws Exception { 727 | 728 | RequestBuilder request = MockMvcRequestBuilders 729 | .get("/dummy-item") 730 | .accept(MediaType.APPLICATION_JSON); 731 | 732 | MvcResult result = mockMvc.perform(request) 733 | .andExpect(status().isOk()) 734 | .andExpect(content().json("{\"id\": 1,\"name\":\"Ball\",\"price\":10,\"quantity\":100}")) 735 | .andReturn(); 736 | //JSONAssert.assertEquals(expected, result.getResponse().getContentAsString(), false); 737 | 738 | } 739 | 740 | @Test 741 | public void itemFromBusinessService_basic() throws Exception { 742 | when(businessService.retreiveHardcodedItem()).thenReturn( 743 | new Item(2,"Item2",10,10)); 744 | 745 | RequestBuilder request = MockMvcRequestBuilders 746 | .get("/item-from-business-service") 747 | .accept(MediaType.APPLICATION_JSON); 748 | 749 | MvcResult result = mockMvc.perform(request) 750 | .andExpect(status().isOk()) 751 | .andExpect(content().json("{id:2,name:Item2,price:10}")) 752 | .andReturn(); 753 | //JSONAssert.assertEquals(expected, result.getResponse().getContentAsString(), false); 754 | 755 | } 756 | 757 | @Test 758 | public void retrieveAllItems_basic() throws Exception { 759 | when(businessService.retrieveAllItems()).thenReturn( 760 | Arrays.asList(new Item(2,"Item2",10,10), 761 | new Item(3,"Item3",20,20)) 762 | ); 763 | 764 | RequestBuilder request = MockMvcRequestBuilders 765 | .get("/all-items-from-database") 766 | .accept(MediaType.APPLICATION_JSON); 767 | 768 | MvcResult result = mockMvc.perform(request) 769 | .andExpect(status().isOk()) 770 | .andExpect(content().json("[{id:3,name:Item3,price:20}, {id:2,name:Item2,price:10}]")) 771 | .andReturn(); 772 | //JSONAssert.assertEquals(expected, result.getResponse().getContentAsString(), false); 773 | 774 | } 775 | 776 | @Test 777 | public void retrieveAllItems_noitems() throws Exception { 778 | when(businessService.retrieveAllItems()).thenReturn( 779 | Arrays.asList() 780 | ); 781 | 782 | RequestBuilder request = MockMvcRequestBuilders 783 | .get("/all-items-from-database") 784 | .accept(MediaType.APPLICATION_JSON); 785 | 786 | MvcResult result = mockMvc.perform(request) 787 | .andExpect(status().isOk()) 788 | .andExpect(content().json("[]")) 789 | .andReturn(); 790 | //JSONAssert.assertEquals(expected, result.getResponse().getContentAsString(), false); 791 | 792 | } 793 | 794 | } 795 | ``` 796 | --- 797 | 798 | ### /src/test/java/com/in28minutes/unittesting/unittesting/data/ItemRepositoryTest.java 799 | 800 | ```java 801 | package com.in28minutes.unittesting.unittesting.data; 802 | 803 | import static org.junit.Assert.assertEquals; 804 | 805 | import java.util.List; 806 | import java.util.Optional; 807 | 808 | import org.junit.Test; 809 | import org.junit.runner.RunWith; 810 | import org.springframework.beans.factory.annotation.Autowired; 811 | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; 812 | import org.springframework.test.context.junit4.SpringRunner; 813 | 814 | import com.in28minutes.unittesting.unittesting.model.Item; 815 | 816 | @RunWith(SpringRunner.class) 817 | @DataJpaTest 818 | public class ItemRepositoryTest { 819 | 820 | @Autowired 821 | private ItemRepository repository; 822 | 823 | @Test 824 | public void testFindAll() { 825 | List items = repository.findAll(); 826 | assertEquals(3,items.size()); 827 | } 828 | 829 | @Test 830 | public void testFindOne() { 831 | Item item = repository.findById(10001).get(); 832 | 833 | assertEquals("Item1",item.getName()); 834 | } 835 | 836 | } 837 | ``` 838 | --- 839 | 840 | ### /src/test/java/com/in28minutes/unittesting/unittesting/spike/AssertJTest.java 841 | 842 | ```java 843 | package com.in28minutes.unittesting.unittesting.spike; 844 | 845 | import static org.assertj.core.api.Assertions.assertThat; 846 | 847 | import java.util.Arrays; 848 | import java.util.List; 849 | 850 | import org.junit.Test; 851 | 852 | public class AssertJTest { 853 | 854 | @Test 855 | public void learning() { 856 | List numbers = Arrays.asList(12,15,45); 857 | 858 | //assertThat(numbers, hasSize(3)); 859 | assertThat(numbers).hasSize(3) 860 | .contains(12,15) 861 | .allMatch(x -> x > 10) 862 | .allMatch(x -> x < 100) 863 | .noneMatch(x -> x < 0); 864 | 865 | assertThat("").isEmpty(); 866 | assertThat("ABCDE").contains("BCD") 867 | .startsWith("ABC") 868 | .endsWith("CDE"); 869 | } 870 | 871 | } 872 | ``` 873 | --- 874 | 875 | ### /src/test/java/com/in28minutes/unittesting/unittesting/spike/HamcrestMatchersTest.java 876 | 877 | ```java 878 | package com.in28minutes.unittesting.unittesting.spike; 879 | 880 | import static org.hamcrest.CoreMatchers.everyItem; 881 | import static org.hamcrest.CoreMatchers.hasItems; 882 | import static org.hamcrest.MatcherAssert.assertThat; 883 | import static org.hamcrest.Matchers.containsString; 884 | import static org.hamcrest.Matchers.endsWith; 885 | import static org.hamcrest.Matchers.greaterThan; 886 | import static org.hamcrest.Matchers.hasSize; 887 | import static org.hamcrest.Matchers.isEmptyString; 888 | import static org.hamcrest.Matchers.lessThan; 889 | import static org.hamcrest.Matchers.startsWith; 890 | 891 | import java.util.Arrays; 892 | import java.util.List; 893 | 894 | import org.junit.Test; 895 | 896 | public class HamcrestMatchersTest { 897 | 898 | @Test 899 | public void learning() { 900 | List numbers = Arrays.asList(12,15,45); 901 | 902 | assertThat(numbers, hasSize(3)); 903 | assertThat(numbers, hasItems(12,45)); 904 | assertThat(numbers, everyItem(greaterThan(10))); 905 | assertThat(numbers, everyItem(lessThan(100))); 906 | 907 | assertThat("", isEmptyString()); 908 | assertThat("ABCDE", containsString("BCD")); 909 | assertThat("ABCDE", startsWith("ABC")); 910 | assertThat("ABCDE", endsWith("CDE")); 911 | 912 | } 913 | 914 | } 915 | ``` 916 | --- 917 | 918 | ### /src/test/java/com/in28minutes/unittesting/unittesting/spike/JsonAssertTest.java 919 | 920 | ```java 921 | package com.in28minutes.unittesting.unittesting.spike; 922 | 923 | import org.json.JSONException; 924 | import org.junit.Test; 925 | import org.skyscreamer.jsonassert.JSONAssert; 926 | 927 | public class JsonAssertTest { 928 | 929 | String actualResponse = "{\"id\":1,\"name\":\"Ball\",\"price\":10,\"quantity\":100}"; 930 | 931 | @Test 932 | public void jsonAssert_StrictTrue_ExactMatchExceptForSpaces() throws JSONException { 933 | String expectedResponse = "{\"id\": 1, \"name\":\"Ball\", \"price\":10, \"quantity\":100}"; 934 | JSONAssert.assertEquals(expectedResponse, actualResponse, true); 935 | } 936 | 937 | @Test 938 | public void jsonAssert_StrictFalse() throws JSONException { 939 | String expectedResponse = "{\"id\": 1, \"name\":\"Ball\", \"price\":10}"; 940 | JSONAssert.assertEquals(expectedResponse, actualResponse, false); 941 | } 942 | 943 | @Test 944 | public void jsonAssert_WithoutEscapeCharacters() throws JSONException { 945 | String expectedResponse = "{id:1, name:Ball, price:10}"; 946 | JSONAssert.assertEquals(expectedResponse, actualResponse, false); 947 | } 948 | } 949 | ``` 950 | --- 951 | 952 | ### /src/test/java/com/in28minutes/unittesting/unittesting/spike/JsonPathTest.java 953 | 954 | ```java 955 | package com.in28minutes.unittesting.unittesting.spike; 956 | 957 | import static org.assertj.core.api.Assertions.assertThat; 958 | 959 | import java.util.List; 960 | 961 | import org.junit.Test; 962 | 963 | import com.jayway.jsonpath.DocumentContext; 964 | import com.jayway.jsonpath.JsonPath; 965 | 966 | public class JsonPathTest { 967 | 968 | @Test 969 | public void learning() { 970 | String responseFromService = "[" + 971 | "{\"id\":10000, \"name\":\"Pencil\", \"quantity\":5}," + 972 | "{\"id\":10001, \"name\":\"Pen\", \"quantity\":15}," + 973 | "{\"id\":10002, \"name\":\"Eraser\", \"quantity\":10}" + 974 | "]"; 975 | 976 | DocumentContext context = JsonPath.parse(responseFromService); 977 | 978 | int length = context.read("$.length()"); 979 | assertThat(length).isEqualTo(3); 980 | 981 | List ids = context.read("$..id"); 982 | 983 | assertThat(ids).containsExactly(10000,10001,10002); 984 | 985 | System.out.println(context.read("$.[1]").toString()); 986 | System.out.println(context.read("$.[0:2]").toString()); 987 | System.out.println(context.read("$.[?(@.name=='Eraser')]").toString()); 988 | System.out.println(context.read("$.[?(@.quantity==5)]").toString()); 989 | 990 | } 991 | 992 | } 993 | ``` 994 | --- 995 | 996 | ### /src/test/java/com/in28minutes/unittesting/unittesting/UnitTestingApplicationTests.java 997 | 998 | ```java 999 | package com.in28minutes.unittesting.unittesting; 1000 | 1001 | import org.junit.Test; 1002 | import org.junit.runner.RunWith; 1003 | import org.springframework.boot.test.context.SpringBootTest; 1004 | import org.springframework.test.context.junit4.SpringRunner; 1005 | 1006 | @RunWith(SpringRunner.class) 1007 | @SpringBootTest 1008 | //@TestPropertySource(locations= {"classpath:test-configuration.properties"}) 1009 | public class UnitTestingApplicationTests { 1010 | 1011 | @Test 1012 | public void contextLoads() { 1013 | } 1014 | 1015 | } 1016 | ``` 1017 | --- 1018 | 1019 | ### /src/test/resources/application.properties 1020 | 1021 | ```properties 1022 | spring.jpa.show-sql=false 1023 | spring.h2.console.enabled=false 1024 | ``` 1025 | --- 1026 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # Master-Java-Unit-Testing-with-Spring-Boot-and-Mockito 5 | Code files 6 | -------------------------------------------------------------------------------- /UnitTestingWithSpringBootAndMockito-CourseGuide.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Master-Java-Unit-Testing-with-Spring-Boot-and-Mockito/36c4b877f11c5a56771c90533a93143a0f23ab73/UnitTestingWithSpringBootAndMockito-CourseGuide.pdf -------------------------------------------------------------------------------- /images/BadTest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Master-Java-Unit-Testing-with-Spring-Boot-and-Mockito/36c4b877f11c5a56771c90533a93143a0f23ab73/images/BadTest.png -------------------------------------------------------------------------------- /images/GoodTest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Master-Java-Unit-Testing-with-Spring-Boot-and-Mockito/36c4b877f11c5a56771c90533a93143a0f23ab73/images/GoodTest.png -------------------------------------------------------------------------------- /images/TestPyramid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Master-Java-Unit-Testing-with-Spring-Boot-and-Mockito/36c4b877f11c5a56771c90533a93143a0f23ab73/images/TestPyramid.png -------------------------------------------------------------------------------- /junit-5-course-guide.md: -------------------------------------------------------------------------------- 1 | # Unit Testing with JUnit 5 2 | 3 | ## Learn Unit Testing with most popular framework - JUnit 5 4 | 5 | JUnit is most popular Java Unit Testing Framework. The new version of JUnit - Junit 5 or Jupiter is even more special. 6 | 7 | In this course, we look into the important features of JUnit 5. We understand the need for unit testing and learn how to write great unit tests with JUnit 5. 8 | 9 | JUnit is a unit testing framework for the Java programming language. 10 | 11 | In this Beginners Tutorial on JUnit 5, you will learn how to 12 | - Create a new project for JUnit Tests 13 | - Create and Run JUnit Tests 14 | - Write Good Unit Tests 15 | - Use assert methods 16 | - Use basic JUnit Annotations - @Test, @BeforeEach, @AfterEach, @AfterAll, @BeforeAll 17 | - Test Performance and Exceptions in Unit Tests 18 | - Write Parameterized Tests 19 | - Adhere to JUnit Best Practices 20 | - Use Eclipse to write and run JUnit Tests 21 | 22 | ### References 23 | - Intellij 24 | - https://www.jetbrains.com/help/idea/configuring-testing-libraries.html 25 | - https://blog.jetbrains.com/idea/2016/08/using-junit-5-in-intellij-idea/ 26 | - Functional Programming - https://youtu.be/aFCNPHfvqEU 27 | - JUnit - https://junit.org/junit5/docs/current/user-guide/ 28 | - Good Unit Testing 29 | - FIRST. https://pragprog.com/magazines/2012-01/unit-tests-are-first 30 | - Patterns - http://xunitpatterns.com 31 | - More Advanced Stuff 32 | - AssertJ - https://joel-costigliola.github.io/assertj/ 33 | - Mockito - https://github.com/mockito/mockito/wiki/FAQ 34 | - JsonPath - https://github.com/json-path/JsonPath 35 | - Setting up JUnit 5 with Mockito and Spring Boot 2.0 - https://medium.com/@dSebastien/using-junit-5-with-spring-boot-2-kotlin-and-mockito-d5aea5b0c668 36 | 37 | ### Recommended Tools 38 | - Java 8 or Later 39 | - Eclipse Oxygen or Later 40 | - Spring Boot 2.0.0.RELEASE or Later 41 | 42 | ### Installing Java 8 and Eclipse 43 | - Installation Video : https://www.youtube.com/playlist?list=PLBBog2r6uMCSmMVTW_QmDLyASBvovyAO3 44 | - GIT Repository For Installation : https://github.com/in28minutes/getting-started-in-5-steps 45 | - PDF : https://github.com/in28minutes/SpringIn28Minutes/blob/master/InstallationGuide-JavaEclipseAndMaven_v2.pdf 46 | 47 | ### What You will learn 48 | - You will learn to write unit tests with JUnit 5 49 | - You will learn to run unit tests with Eclipse 50 | - You will learn about variety of JUnit assert methods 51 | - You will understand basic JUnit Annotations - @Test, @BeforeEach, @AfterEach, @AfterAll, @BeforeAll 52 | - You will learn to test performance and exceptions in unit tests 53 | - You will learn to write parameterized tests 54 | - You will learn the differences between JUnit 4 and JUnit 5 55 | - You will learn about the JUnit Best Practices 56 | 57 | ### Requirements 58 | - You should have working knowledge of Java and Annotations. 59 | - We will help you install Eclipse and get up and running with Maven and Tomcat. 60 | 61 | ### Exercises 62 | - Step 04 - First Unit Test with JUnit - String length() method 63 | - Write unit test for Math.min and Math.max methods! 64 | - Step 05 - Writing JUnit Assertions - assertNull and assertTrue 65 | - Exercise : Write assertEquals for two other data types 66 | - Step 06 - Writing Assertions for Arrays - assertArrayEquals 67 | - Spot the bug : Reverse expected and actual values 68 | - Step 11 - Basics of Parameterized tests 69 | - Write unit tests using ints attribute of Parameterized Test for a Math method. 70 | 71 | ### Step By Step Details 72 | - Step 01 - Introduction to Unit Testing - Test Pyramid 73 | - Step 02 - First Junit Test - Red bar 74 | - Step 03 - Absence of failure is success 75 | - Step 04 - First Unit Test with JUnit - String length() method 76 | - Step 05 - Writing JUnit Assertions - assertNull and assertTrue 77 | - Step 06 - Writing Assertions for Arrays - assertArrayEquals 78 | - Step 07 - Setting up data for every test - @BeforeEach, @AfterEach 79 | - Step 08 - Setting up database connections - @BeforeAll, @AfterAll 80 | - Step 09 - Tip - Testing Exceptions with JUnit 81 | - Step 10 - Tip - @DisplayName and test methods need not be public 82 | - Step 11 - Basics of Parameterized tests 83 | - Step 12 - Advanced Paramaterized Tests with Csv Source 84 | - Step 13 - Tip - Giving a name to a Parameterized Test 85 | - Step 14 - Tip - Repeat same test multiple times 86 | - Step 15 - Tip - Unit Testing for Performance 87 | - Step 16 - Tip - Disable Unit Tests 88 | - Step 17 - Tip - Grouping Tests with @Nested 89 | - Step 18 - Tip - JUnit 5 = Platform + Jupiter + Vintage 90 | - Step 19 - Tip - JUnit 4 vs JUnit 5 91 | - Step 20 - Tip - JUnit Best Practices 92 | - Step 21 - Tip - JUnit Patterns - http://xunitpatterns.com 93 | 94 | ### Course Notes 95 | 96 | #### Test Pyramid 97 | ![Test Pyramid](images/TestPyramid.png) 98 | 99 | #### JUnit 5 100 | JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage 101 | - JUnit Platform = Building Blocks 102 | - JUnit Jupiter = new programming model + extension model + extensions - assertions, annotations 103 | - JUnit Vintage = Support for old JUnit version ( 3 & 4) 104 | 105 | #### JUnit 5 vs JUnit 4 106 | - Neither test classes nor test methods need to be public 107 | 108 | Annotations 109 | - Same as in JUnit 4 - @Test 110 | - Renamed 111 | - @BeforeAll instead of @BeforeClass 112 | - @AfterAll instead of @AfterClass 113 | - @BeforeEach instead of @Before 114 | - @AfterEach instead of @After 115 | - @Disable instead of @Ignore 116 | - @Tag instead of @Category 117 | - New 118 | - @DisplayName 119 | - @TestFactory for dynamic tests 120 | - @Nested for nested tests 121 | - @RepeatedTest to executed tests multiple times 122 | - @EnabledOnOs 123 | - @DisabledOnOs 124 | - @EnabledOnJre 125 | 126 | Assertions 127 | - Same as JUnit 4 128 | - assertTrue, assertSame, assertNull, assertNotSame, assertNotEquals, assertNotNull, assertFalse, assertEquals, assertArrayEquals 129 | - New 130 | - assertThrows and assertTimeout 131 | 132 | ### Course Recording Notes 133 | 134 | #### Preview Video 135 | - Welcome to course on *** in ** simple steps. 136 | - I'm Ranga Karanam. I've so and so much experience with ... I've been using this framework for ... 137 | - At in28minutes, we ask one question everyday - How to create more effective courses? All our success - *** students on Udemy and *** subscribers on Youtube - is a result of this pursuit of excellence. 138 | - You will develop *** and *** using *** 139 | - You will learn the basics like *** and move on to the advanced concepts like ***. 140 | - You will use 141 | - ... todo ... 142 | - Maven for dependency management, building and running the application in tomcat. 143 | - Eclipse IDE 144 | - All the code for this course and the step by step details are in our Github repository. 145 | - We have an awesome installation guide to help you install Maven and Eclipse. You are NOT expected to have any experience with Eclipse, Maven, or Tomcat. 146 | - What are we waiting for? Lets have some fun with *** in *** steps. We had a lot of fun creating this course for you and We are confident that you will have a lot of fun. I hope you are as excited as we are to learn more. Go ahead and enroll for the course. Or take a test drive with a free preview. See you in the course. 147 | 148 | #### Conclusion Video 149 | - Congratulations! You have successfully completed the course on ... We covered a wide range of topics starting from Spring, Spring Boot to ..... I'm sure you had a lot of fun doing this course. If you loved this course, we would love to hear from you. Do not forget to leave us a review. Until we see you in another in28minutes course, here's bye from the team here at in28minutes. 150 | - To find out more about *** use these References 151 | 152 | ## Templates 153 | 154 | ### Welcome Message 155 | ``` 156 | 157 | ## ADD A FEW SAMPLE REVIEWS AFter a couple of months 158 | ## ADD A FEW SAMPLE REVIEWS - in the description of the course 159 | 160 | Congratulations on joining this course from in28Minutes. 161 | 162 | We have 6800+ 5 Star reviews on our courses. 163 | 164 | I hope that by the time you are prompted to leave a review, that you think this course is an amazing course and can write a few sentences about what you like about the course for future students to see. If you do not think this course is a 5-star course, we want to make it a better course for you! Please message me with ways that I can make it the best course for you. 165 | 166 | There are three things you need to understand before you start this course! 167 | 168 | 1...... Listen + See + Do Hands-on + Repeat = 90% Retention 169 | For the first 2 hours, we repeat a few concepts to help you retain them. . 170 | 171 | 2...... Set Yourself a Goal 172 | Set 1 hour aside every day for the next week for this course! No exceptions allowed :) 173 | 174 | 3...... Udemy asks you for a review very early in the course! If you are not ready for giving a review, you can skip giving a review. 175 | 176 | Thank you and enjoy the course, 177 | Ranga 178 | ``` 179 | 180 | ### Thank You for completing the course message 181 | 182 | ``` 183 | Congratulations on completing the course from in28Minutes. 184 | 185 | We have 6800+ 5 Star reviews on our courses. We hope you think this course is an amazing course and can write a few sentences about what you like about the course for future students to see. 186 | 187 | We are on a constant journey to improve our courses further. Do message me if you have any suggestions. 188 | 189 | Good Luck for your future. 190 | 191 | Ranga from in28Minutes 192 | ``` 193 | 194 | ### Bonus Lectures 195 | 196 | ``` 197 | Our Best Selling Courses 198 | Get unbelievable offers on all our best-selling courses! 199 | http://eepurl.com/bOJulL 200 | ``` 201 | 202 | ### JUnit 5 Complete Code Example 203 | 204 | ```java 205 | package com.in28minutes.junit5; 206 | 207 | import static org.junit.jupiter.api.Assertions.assertArrayEquals; 208 | import static org.junit.jupiter.api.Assertions.assertEquals; 209 | import static org.junit.jupiter.api.Assertions.assertFalse; 210 | import static org.junit.jupiter.api.Assertions.assertNotNull; 211 | import static org.junit.jupiter.api.Assertions.assertThrows; 212 | import static org.junit.jupiter.api.Assertions.assertTimeout; 213 | import static org.junit.jupiter.api.Assertions.assertTrue; 214 | 215 | import java.time.Duration; 216 | 217 | import org.junit.jupiter.api.AfterAll; 218 | import org.junit.jupiter.api.AfterEach; 219 | import org.junit.jupiter.api.BeforeAll; 220 | import org.junit.jupiter.api.BeforeEach; 221 | import org.junit.jupiter.api.Disabled; 222 | import org.junit.jupiter.api.DisplayName; 223 | import org.junit.jupiter.api.Nested; 224 | import org.junit.jupiter.api.RepeatedTest; 225 | import org.junit.jupiter.api.Test; 226 | import org.junit.jupiter.api.TestInfo; 227 | import org.junit.jupiter.params.ParameterizedTest; 228 | import org.junit.jupiter.params.provider.CsvSource; 229 | import org.junit.jupiter.params.provider.ValueSource; 230 | 231 | class StringTest { 232 | 233 | private String str; 234 | 235 | @BeforeAll 236 | static void beforeAll() { 237 | System.out.println("Initialize connection to database"); 238 | } 239 | 240 | @AfterAll 241 | static void afterAll() { 242 | System.out.println("Close connection to database"); 243 | } 244 | 245 | @BeforeEach // @Before 246 | void beforeEach(TestInfo info) { 247 | System.out.println("Initialize Test Data for " + info.getDisplayName()); 248 | } 249 | 250 | @AfterEach // @After 251 | void afterEach(TestInfo info) { 252 | System.out.println("Clean up Test Data for " + info.getDisplayName()); 253 | } 254 | 255 | @Test 256 | @Disabled // @Ignored 257 | void length_basic() { 258 | int actualLength = "ABCD".length(); 259 | int expectedLength = 4; 260 | assertEquals(expectedLength, actualLength); 261 | // Assert length == 4 262 | // Write test code 263 | // Invoke method square(4) => CUT 264 | // Checks in place - 16 => Assertions 265 | } 266 | 267 | @Test 268 | void length_greater_than_zero() { 269 | assertTrue("ABCD".length() > 0); 270 | assertTrue("ABC".length() > 0); 271 | assertTrue("A".length() > 0); 272 | assertTrue("DEF".length() > 0); 273 | } 274 | 275 | @ParameterizedTest 276 | @ValueSource(strings = { "ABCD", "ABC", "A", "DEF" }) 277 | void length_greater_than_zero_using_parameterized_test(String str) { 278 | assertTrue(str.length() > 0); 279 | } 280 | 281 | @ParameterizedTest(name = "{0} toUpperCase is {1}") 282 | @CsvSource(value = { "abcd, ABCD", "abc, ABC", "'',''", "abcdefg, ABCDEFG" }) 283 | void uppercase(String word, String capitalizedWord) { 284 | assertEquals(capitalizedWord, word.toUpperCase()); 285 | } 286 | 287 | @ParameterizedTest(name = "{0} length is {1}") 288 | @CsvSource(value = { "abcd, 4", "abc, 3", "'',0", "abcdefg, 7" }) 289 | void length(String word, int expectedLength) { 290 | assertEquals(expectedLength, word.length()); 291 | } 292 | 293 | @Test 294 | @DisplayName("When length is null, throw an exception") 295 | void length_exception() { 296 | 297 | String str = null; 298 | 299 | assertThrows(NullPointerException.class, 300 | 301 | () -> { 302 | str.length(); 303 | } 304 | 305 | ); 306 | } 307 | 308 | @Test 309 | @Disabled 310 | void performanceTest() { 311 | assertTimeout(Duration.ofSeconds(5), () -> { 312 | for (int i = 0; i <= 1000000; i++) { 313 | int j = i; 314 | System.out.println(j); 315 | } 316 | } 317 | 318 | ); 319 | } 320 | 321 | @Test 322 | void toUpperCase_basic() { 323 | String str = "abcd"; 324 | String result = str.toUpperCase(); 325 | assertNotNull(result); 326 | // assertNull(result); 327 | assertEquals("ABCD", result); 328 | } 329 | 330 | @Test 331 | @RepeatedTest(1) 332 | void contains_basic() { 333 | assertFalse("abcdefgh".contains("ijk")); 334 | } 335 | 336 | @Test 337 | void split_basic() { 338 | String str = "abc def ghi"; 339 | String actualResult[] = str.split(" "); 340 | String[] expectedResult = new String[] { "abc", "def", "ghi" }; 341 | assertArrayEquals(expectedResult, actualResult); 342 | } 343 | 344 | @Nested 345 | @DisplayName("For an empty String") 346 | class EmptyStringTests { 347 | 348 | @BeforeEach 349 | void setToEmpty() { 350 | str = ""; 351 | } 352 | 353 | @Test 354 | @DisplayName("length should be zero") 355 | void lengthIsZero() { 356 | assertEquals(0,str.length()); 357 | } 358 | 359 | @Test 360 | @DisplayName("upper case is empty") 361 | void uppercaseIsEmpty() { 362 | assertEquals("",str.toUpperCase()); 363 | } 364 | 365 | } 366 | 367 | @Nested 368 | @DisplayName("For large strings") 369 | class LargeStringTests { 370 | 371 | @BeforeEach 372 | void setToALargeString() { 373 | str = "Afsjdjfljsadfkljsadlkfjlajbvjcxzbnhrewu"; 374 | } 375 | 376 | @Test 377 | void test() { 378 | 379 | } 380 | 381 | } 382 | } 383 | ``` 384 | 385 | ### Useful Links 386 | - [Our Website](http://www.in28minutes.com) 387 | - [Facebook](http://facebook.com/in28minutes) 388 | - [Twitter](http://twitter.com/in28minutes) 389 | - [Google Plus](https://plus.google.com/u/3/110861829188024231119) -------------------------------------------------------------------------------- /link.txt: -------------------------------------------------------------------------------- 1 | https://github.com/in28minutes/in28minutes-initiatives/blob/master/The-in28Minutes-TroubleshootingGuide-And-FAQ/quick-start.md -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.in28minutes.unittesting 7 | unit-testing 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | unit-testing 12 | Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.4.0 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 3.1.1 26 | 27 | 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-starter-web 32 | 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-starter-data-jpa 37 | 38 | 39 | 40 | com.h2database 41 | h2 42 | 43 | 44 | org.springframework.boot 45 | spring-boot-devtools 46 | runtime 47 | 48 | 49 | org.springframework.boot 50 | spring-boot-starter-test 51 | test 52 | 53 | 54 | 55 | 56 | 57 | 58 | org.springframework.boot 59 | spring-boot-maven-plugin 60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Unit Testing with Spring, JUnit and Mockito 2 | 3 | [![Image](https://www.springboottutorial.com/images/Course-Master-Java-Unit-Testing-with-Spring-Boot-Mockito.png "Master Java Unit Testing with Spring Boot & Mockito")](https://www.udemy.com/course/learn-unit-testing-with-spring-boot/) 4 | 5 | ## Learn Unit Testing with most popular frameworks - Spring Boot, JUnit and Mockito 6 | 7 | Spring Boot is the most popular framework to develop RESTful Services. It has awesome unit testing capabilities through Spring Boot Starter Test. Mockito is the most popular mocking framework. JUnit is most popular Java Unit Testing Framework. 8 | 9 | In this course, you will learn to build unit tests for simple RESTful Services with Spring Boot Starter Test, Mockito and JUnit. You will learn to write independent unit tests for RESTful web services talking with multiple layers - web, business and data. You will learn how to write integration tests using an in memory database H2. 10 | 11 | You will build the unit tests step by step - in more than 50 steps. This course would be a perfect first step as an introduction to unit testing with Spring Boot and Mockito Frameworks. 12 | 13 | You will be using Spring (Dependency Management), Spring Boot, Maven (dependencies management), Eclipse (IDE), in memory database H2 and Tomcat Embedded Web Server. We will help you set up each one of these. 14 | 15 | You will use all the frameworks that are part of Spring Boot Starter Test - JUnit, Spring Test, Spring Boot Test, AssertJ, Hamcrest, Mockito, JSONassert and JsonPath. 16 | 17 | You will learn to use the most important Unit Testing Annotations - @RunWith(SpringRunner.class), @SpringBootTest, @WebMvcTest, @DataJpaTest and @MockBean. 18 | 19 | ### Recommended Tools 20 | - Java 8 or Later 21 | - Eclipse Oxygen or Later 22 | - Spring Boot 2.0.0.RELEASE or Later 23 | 24 | ### Installing Java 8 and Eclipse 25 | - Installation Video : https://www.youtube.com/playlist?list=PLBBog2r6uMCSmMVTW_QmDLyASBvovyAO3 26 | - GIT Repository For Installation : https://github.com/in28minutes/getting-started-in-5-steps 27 | - PDF : https://github.com/in28minutes/SpringIn28Minutes/blob/master/InstallationGuide-JavaEclipseAndMaven_v2.pdf 28 | 29 | ### References 30 | - Intellij 31 | - https://www.jetbrains.com/help/idea/configuring-testing-libraries.html 32 | - https://blog.jetbrains.com/idea/2016/08/using-junit-5-in-intellij-idea/ 33 | - Spring & Spring Boot Framework - https://www.youtube.com/watch?v=PSP1-2cN7vM&t=893s 34 | - Introduction to JPA and Hibernate using Spring Boot Data Jpa - http://www.springboottutorial.com/introduction-to-jpa-with-spring-boot-data-jpa 35 | - Functional Programming - https://youtu.be/aFCNPHfvqEU 36 | - JUnit - https://junit.org/junit5/docs/current/user-guide/ 37 | - AssertJ - https://joel-costigliola.github.io/assertj/ 38 | - Mockito - https://github.com/mockito/mockito/wiki/FAQ 39 | - JsonPath - https://github.com/json-path/JsonPath 40 | - Setting up JUnit 5 with Mockito and Spring Boot 2.0 - https://medium.com/@dSebastien/using-junit-5-with-spring-boot-2-kotlin-and-mockito-d5aea5b0c668 41 | - Good Unit Testing 42 | - https://github.com/mockito/mockito/wiki/How-to-write-good-tests 43 | - FIRST. https://pragprog.com/magazines/2012-01/unit-tests-are-first 44 | - Patterns - http://xunitpatterns.com 45 | - Mocking Static, Private Methods and Constructors 46 | - https://github.com/in28minutes/MockitoTutorialForBeginners/blob/master/Step15.md 47 | - https://github.com/in28minutes/MockitoTutorialForBeginners/tree/master/src/test/java/com/in28minutes/powermock 48 | 49 | ### Mockito 50 | 51 | Easier Static Imports 52 | ``` 53 | Window > Preferences > Java > Editor > Content Assist > Favorites 54 | org.junit.Assert 55 | org.mockito.BDDMockito 56 | org.mockito.Mockito 57 | org.assertj.core.api.Assertions 58 | org.hamcrest.Matchers 59 | org.hamcrest.CoreMatchers 60 | org.hamcrest.MatcherAssert 61 | ``` 62 | ### What You will learn 63 | - You will learn to write great Unit and Integration tests using Spring Boot Starter Test 64 | - You will learn to write unit tests using Mocks and Spys created with Mockito 65 | - You will learn to write independent unit tests for RESTful web services talking with multiple layers - web, business and data 66 | - You will learn to write integration tests using an in memory database - H2 67 | - You will learn to use all the frameworks that are part of Spring Boot Starter Test - JUnit, Spring Test, Spring Boot Test, AssertJ, Hamcrest, Mockito, JSONassert and JsonPath. 68 | - You will learn to use the most important Unit Testing Annotations - @RunWith(SpringRunner.class), @SpringBootTest, @WebMvcTest, @DataJpaTest and @MockBean. 69 | 70 | ### Requirements 71 | - You should have working knowledge of Java and Annotations. 72 | - We will help you install Eclipse and get up and running with Maven and Tomcat. 73 | - You should have basic knowledge about Spring, Spring Boot and JPA/Hibernate. We provide resources that can be used as starting points to enrich your knowledge in the course. 74 | 75 | ## Mockito 76 | 77 | ### Step By Step Details 78 | 79 | - Step 01: Setting up the project using Spring Initializr 80 | - Step 02: Writing Unit Test for a Simple Business Service 81 | - Step 03: Setting up a Business Service to call a Data Service 82 | - Step 04: Writing your first unit test with Stub 83 | - Exercise - Update Tests 2 & 3 84 | - Step 05: Exercise Solution - Updating Tests 2 & 3 to use Stubs - Problem with Stubs. 85 | - Step 06: Writing Unit Tests with Mocking using Mockito 86 | - Exercise - Updating Tests 2 & 3 to use Mockito 87 | - Step 07: Exercise Solution - Updating Tests 2 & 3 to use Mockito 88 | - Step 08: More Refactoring - @Mock, @InjectMocks and @RunWith(MockitoJUnitRunner.class) 89 | - Step 09: Mockito Tips - Multiple Return Values and Specific Argument Matchers 90 | - Step 10: Mockito Tips - Argument Matchers 91 | - Step 11: Mockito Tips - Verify method calls 92 | - Step 12: Mockito Tips - Argument Capture 93 | - Step 13: Mockito Tips - Argument Capture on Multiple Calls 94 | - Step 14: Introduction to Spy 95 | - Step 15: Mockito FAQ 96 | 97 | ## Spring Boot & Mockito - Unit Testing 98 | 99 | ### Step By Step Details 100 | 101 | - Step 01: Creating a Hello World Controller 102 | - Step 02: Using Mock Mvc to test Hello World Controller 103 | - Step 03: Using Response Matchers to check status and content 104 | - Step 04: Creating a Basic REST Service in Item Controller 105 | - Step 05: Unit Testing Item Controller and Basic JSON Assertions 106 | - Step 06: Digging deeper into JSON Assert 107 | - Step 07: Writing a REST Service talking to Business Layer 108 | - Step 08: Writing Unit Test for REST Service mocking Business Layer 109 | - Step 09 - 01 - Prepare Data Layers with JPA, Hibernate and H2 110 | - Step 10: Create Item Entity and Populate data with data.sql 111 | - Step 11: Create a RESTful Service talking to the database 112 | - Step 12: Writing Unit Test for Web Layer - Controller - Using Mock MVC 113 | - Step 13: Exercise & Solution - Writing Unit Test for Business Layer - Mocking 114 | - Step 14: Writing Unit Test for Data Layer - Data JPA Test 115 | - Exercise - Write Unit Test for findById method retrieving item with id 10001 116 | - Step 15: Writing an Integration Test using @SpringBootTest 117 | - Exercise - Make Asserts Better 118 | - Step 16: Tip : Using @MockBean to mock out dependencies you do not want to talk to! 119 | - Step 17: Tip : Creating Different Test Configuration 120 | - Step 18: Writing Unit Tests for Other Request Methods 121 | - Step 19: Refactor SomeBusinessImpl to use Functional Programming 122 | - Exercise - Convert the second method to use Functional Approach 123 | - Step 20: Better Assertions with Hamcrest - HamcrestMatcherTest 124 | - Step 21: Better Assertions with AssertJ - AssertJTest 125 | - Step 22: Better Assertions with JSONPath - JSONPathTest 126 | - Step 23: Easier Static Imports 127 | - Step 24: Tip : Measuring Test Coverage with Eclipse 128 | - Step 25: Tip : Keep an eye on performance of unit tests! 129 | - Step 26: Good Unit Tests 130 | 131 | 132 | ### Troubleshooting 133 | - Refer our TroubleShooting Guide - https://github.com/in28minutes/in28minutes-initiatives/tree/master/The-in28Minutes-TroubleshootingGuide-And-FAQ 134 | 135 | ## Youtube Playlists - 500+ Videos 136 | 137 | [Click here - 30+ Playlists with 500+ Videos on Spring, Spring Boot, REST, Microservices and the Cloud](https://www.youtube.com/user/rithustutorials/playlists?view=1&sort=lad&flow=list) 138 | 139 | ## Keep Learning in28Minutes 140 | 141 | in28Minutes is creating amazing solutions for you to learn Spring Boot, Full Stack and the Cloud - Docker, Kubernetes, AWS, React, Angular etc. - [Check out all our courses here](https://github.com/in28minutes/learn) 142 | 143 | ![in28MinutesLearningRoadmap-July2019.png](https://github.com/in28minutes/in28Minutes-Course-Roadmap/raw/master/in28MinutesLearningRoadmap-July2019.png) 144 | -------------------------------------------------------------------------------- /src/main/java/com/in28minutes/unittesting/unittesting/UnitTestingApplication.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.unittesting.unittesting; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class UnitTestingApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(UnitTestingApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/in28minutes/unittesting/unittesting/business/ItemBusinessService.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.unittesting.unittesting.business; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Component; 7 | 8 | import com.in28minutes.unittesting.unittesting.data.ItemRepository; 9 | import com.in28minutes.unittesting.unittesting.model.Item; 10 | 11 | @Component 12 | public class ItemBusinessService { 13 | 14 | @Autowired 15 | private ItemRepository repository; 16 | 17 | public Item retreiveHardcodedItem() { 18 | return new Item(1, "Ball", 10, 100); 19 | } 20 | 21 | public List retrieveAllItems() { 22 | List items = repository.findAll(); 23 | 24 | for(Item item:items) { 25 | item.setValue(item.getPrice() * item.getQuantity()); 26 | } 27 | 28 | return items; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/in28minutes/unittesting/unittesting/business/SomeBusinessImpl.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.unittesting.unittesting.business; 2 | 3 | import com.in28minutes.unittesting.unittesting.data.SomeDataService; 4 | 5 | public class SomeBusinessImpl { 6 | 7 | private SomeDataService someDataService; 8 | 9 | public void setSomeDataService(SomeDataService someDataService) { 10 | this.someDataService = someDataService; 11 | } 12 | 13 | public int calculateSum(int[] data) { 14 | int sum = 0; 15 | for(int value:data) { 16 | sum += value; 17 | } 18 | return sum; 19 | //Functional Style 20 | //return Arrays.stream(data).reduce(Integer::sum).orElse(0); 21 | } 22 | 23 | public int calculateSumUsingDataService() { 24 | int sum = 0; 25 | int[] data = someDataService.retrieveAllData(); 26 | for(int value:data) { 27 | sum += value; 28 | } 29 | 30 | //someDataService.storeSum(sum); 31 | return sum; 32 | //Functional Style 33 | //return Arrays.stream(data).reduce(Integer::sum).orElse(0); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/in28minutes/unittesting/unittesting/controller/HelloWorldController.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.unittesting.unittesting.controller; 2 | 3 | import org.springframework.web.bind.annotation.GetMapping; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | @RestController 7 | public class HelloWorldController { 8 | 9 | @GetMapping("/hello-world") 10 | public String helloWorld() { 11 | return "Hello World"; 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/in28minutes/unittesting/unittesting/controller/ItemController.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.unittesting.unittesting.controller; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | import com.in28minutes.unittesting.unittesting.business.ItemBusinessService; 10 | import com.in28minutes.unittesting.unittesting.model.Item; 11 | 12 | @RestController 13 | public class ItemController { 14 | 15 | @Autowired 16 | private ItemBusinessService businessService; 17 | 18 | @GetMapping("/dummy-item") 19 | public Item dummyItem() { 20 | return new Item(1, "Ball", 10, 100); 21 | } 22 | 23 | @GetMapping("/item-from-business-service") 24 | public Item itemFromBusinessService() { 25 | Item item = businessService.retreiveHardcodedItem(); 26 | 27 | return item; 28 | } 29 | 30 | @GetMapping("/all-items-from-database") 31 | public List retrieveAllItems() { 32 | return businessService.retrieveAllItems(); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/in28minutes/unittesting/unittesting/data/ItemRepository.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.unittesting.unittesting.data; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | import com.in28minutes.unittesting.unittesting.model.Item; 6 | 7 | public interface ItemRepository extends JpaRepository{ 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/in28minutes/unittesting/unittesting/data/SomeDataService.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.unittesting.unittesting.data; 2 | 3 | public interface SomeDataService { 4 | 5 | int[] retrieveAllData(); 6 | 7 | //int retrieveSpecificData(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/in28minutes/unittesting/unittesting/model/Item.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.unittesting.unittesting.model; 2 | 3 | import javax.persistence.Entity; 4 | import javax.persistence.Id; 5 | import javax.persistence.Transient; 6 | 7 | @Entity 8 | public class Item { 9 | 10 | @Id 11 | private int id; 12 | private String name; 13 | private int price; 14 | private int quantity; 15 | 16 | @Transient 17 | private int value; 18 | 19 | protected Item() { 20 | 21 | } 22 | 23 | public Item(int id, String name, int price, int quantity) { 24 | this.id = id; 25 | this.name = name; 26 | this.price = price; 27 | this.quantity = quantity; 28 | } 29 | 30 | public int getId() { 31 | return id; 32 | } 33 | 34 | public String getName() { 35 | return name; 36 | } 37 | 38 | public int getPrice() { 39 | return price; 40 | } 41 | 42 | public int getQuantity() { 43 | return quantity; 44 | } 45 | 46 | public int getValue() { 47 | return value; 48 | } 49 | 50 | public void setValue(int value) { 51 | this.value = value; 52 | } 53 | 54 | public String toString() { 55 | return String.format("Item[%d, %s, %d, %d]", id, name, price, quantity); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.jpa.show-sql=true 2 | spring.h2.console.enabled=true -------------------------------------------------------------------------------- /src/main/resources/data.sql: -------------------------------------------------------------------------------- 1 | insert into item(id, name, price, quantity) values(10001,'Item1',10,20); 2 | insert into item(id, name, price, quantity) values(10002,'Item2',5,10); 3 | insert into item(id, name, price, quantity) values(10003,'Item3',15,2); -------------------------------------------------------------------------------- /src/test/java/com/in28minutes/unittesting/unittesting/UnitTestingApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.unittesting.unittesting; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | //@TestPropertySource(locations= {"classpath:test-configuration.properties"}) 8 | public class UnitTestingApplicationTests { 9 | 10 | @Test 11 | public void contextLoads() { 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/test/java/com/in28minutes/unittesting/unittesting/business/ItemBusinessServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.unittesting.unittesting.business; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.mockito.Mockito.when; 5 | 6 | import java.util.Arrays; 7 | import java.util.List; 8 | 9 | import org.junit.jupiter.api.Test; 10 | import org.junit.jupiter.api.extension.ExtendWith; 11 | import org.mockito.InjectMocks; 12 | import org.mockito.Mock; 13 | import org.mockito.junit.jupiter.MockitoExtension; 14 | 15 | import com.in28minutes.unittesting.unittesting.data.ItemRepository; 16 | import com.in28minutes.unittesting.unittesting.model.Item; 17 | 18 | @ExtendWith(MockitoExtension.class) 19 | public class ItemBusinessServiceTest { 20 | 21 | @InjectMocks 22 | private ItemBusinessService business; 23 | 24 | @Mock 25 | private ItemRepository repository; 26 | 27 | @Test 28 | public void retrieveAllItems_basic() { 29 | when(repository.findAll()).thenReturn(Arrays.asList(new Item(2,"Item2",10,10), 30 | new Item(3,"Item3",20,20))); 31 | List items = business.retrieveAllItems(); 32 | 33 | assertEquals(100, items.get(0).getValue()); 34 | assertEquals(400, items.get(1).getValue()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/com/in28minutes/unittesting/unittesting/business/ListMockTest.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.unittesting.unittesting.business; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.mockito.ArgumentMatchers.anyInt; 5 | import static org.mockito.Mockito.atLeast; 6 | import static org.mockito.Mockito.atLeastOnce; 7 | import static org.mockito.Mockito.atMost; 8 | import static org.mockito.Mockito.mock; 9 | import static org.mockito.Mockito.never; 10 | import static org.mockito.Mockito.spy; 11 | import static org.mockito.Mockito.times; 12 | import static org.mockito.Mockito.verify; 13 | import static org.mockito.Mockito.when; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | 18 | import org.junit.jupiter.api.Disabled; 19 | import org.junit.jupiter.api.Test; 20 | import org.mockito.ArgumentCaptor; 21 | 22 | public class ListMockTest { 23 | 24 | List mock = mock(List.class); 25 | 26 | @Test 27 | public void size_basic() { 28 | when(mock.size()).thenReturn(5); 29 | assertEquals(5, mock.size()); 30 | } 31 | 32 | @Test 33 | public void returnDifferentValues() { 34 | when(mock.size()).thenReturn(5).thenReturn(10); 35 | assertEquals(5, mock.size()); 36 | assertEquals(10, mock.size()); 37 | } 38 | 39 | @Test 40 | @Disabled 41 | public void returnWithParameters() { 42 | when(mock.get(0)).thenReturn("in28Minutes"); 43 | assertEquals("in28Minutes", mock.get(0)); 44 | assertEquals(null, mock.get(1)); 45 | } 46 | 47 | @Test 48 | public void returnWithGenericParameters() { 49 | when(mock.get(anyInt())).thenReturn("in28Minutes"); 50 | 51 | assertEquals("in28Minutes", mock.get(0)); 52 | assertEquals("in28Minutes", mock.get(1)); 53 | } 54 | 55 | @Test 56 | public void verificationBasics() { 57 | // SUT 58 | String value1 = mock.get(0); 59 | String value2 = mock.get(1); 60 | 61 | // Verify 62 | verify(mock).get(0); 63 | verify(mock, times(2)).get(anyInt()); 64 | verify(mock, atLeast(1)).get(anyInt()); 65 | verify(mock, atLeastOnce()).get(anyInt()); 66 | verify(mock, atMost(2)).get(anyInt()); 67 | verify(mock, never()).get(2); 68 | } 69 | 70 | @Test 71 | public void argumentCapturing() { 72 | 73 | //SUT 74 | mock.add("SomeString"); 75 | 76 | //Verification 77 | ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); 78 | verify(mock).add(captor.capture()); 79 | 80 | assertEquals("SomeString", captor.getValue()); 81 | 82 | } 83 | 84 | @Test 85 | public void multipleArgumentCapturing() { 86 | 87 | //SUT 88 | mock.add("SomeString1"); 89 | mock.add("SomeString2"); 90 | 91 | //Verification 92 | ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); 93 | 94 | verify(mock, times(2)).add(captor.capture()); 95 | 96 | List allValues = captor.getAllValues(); 97 | 98 | assertEquals("SomeString1", allValues.get(0)); 99 | assertEquals("SomeString2", allValues.get(1)); 100 | 101 | } 102 | 103 | @Test 104 | public void mocking() { 105 | ArrayList arrayListMock = mock(ArrayList.class); 106 | System.out.println(arrayListMock.get(0));//null 107 | System.out.println(arrayListMock.size());//0 108 | arrayListMock.add("Test"); 109 | arrayListMock.add("Test2"); 110 | System.out.println(arrayListMock.size());//0 111 | when(arrayListMock.size()).thenReturn(5); 112 | System.out.println(arrayListMock.size());//5 113 | } 114 | 115 | @Test 116 | public void spying() { 117 | ArrayList arrayListSpy = spy(ArrayList.class); 118 | arrayListSpy.add("Test0"); 119 | System.out.println(arrayListSpy.get(0));//Test0 120 | System.out.println(arrayListSpy.size());//1 121 | arrayListSpy.add("Test"); 122 | arrayListSpy.add("Test2"); 123 | System.out.println(arrayListSpy.size());//3 124 | 125 | when(arrayListSpy.size()).thenReturn(5); 126 | System.out.println(arrayListSpy.size());//5 127 | 128 | arrayListSpy.add("Test4"); 129 | System.out.println(arrayListSpy.size());//5 130 | 131 | verify(arrayListSpy).add("Test4"); 132 | } 133 | 134 | 135 | } 136 | -------------------------------------------------------------------------------- /src/test/java/com/in28minutes/unittesting/unittesting/business/SomeBusinessMockTest.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.unittesting.unittesting.business; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.mockito.Mockito.when; 5 | 6 | import org.junit.jupiter.api.Test; 7 | import org.junit.jupiter.api.extension.ExtendWith; 8 | import org.mockito.InjectMocks; 9 | import org.mockito.Mock; 10 | import org.mockito.junit.jupiter.MockitoExtension; 11 | 12 | import com.in28minutes.unittesting.unittesting.data.SomeDataService; 13 | 14 | @ExtendWith(MockitoExtension.class) 15 | public class SomeBusinessMockTest { 16 | 17 | @InjectMocks 18 | SomeBusinessImpl business; 19 | 20 | @Mock 21 | SomeDataService dataServiceMock; 22 | 23 | @Test 24 | public void calculateSumUsingDataService_basic() { 25 | when(dataServiceMock.retrieveAllData()).thenReturn(new int[] { 1, 2, 3 }); 26 | assertEquals(6, business.calculateSumUsingDataService()); 27 | } 28 | 29 | @Test 30 | public void calculateSumUsingDataService_empty() { 31 | when(dataServiceMock.retrieveAllData()).thenReturn(new int[] {}); 32 | assertEquals(0, business.calculateSumUsingDataService()); 33 | } 34 | 35 | @Test 36 | public void calculateSumUsingDataService_oneValue() { 37 | when(dataServiceMock.retrieveAllData()).thenReturn(new int[] { 5 }); 38 | assertEquals(5, business.calculateSumUsingDataService()); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/test/java/com/in28minutes/unittesting/unittesting/business/SomeBusinessStubTest.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.unittesting.unittesting.business; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | import com.in28minutes.unittesting.unittesting.data.SomeDataService; 8 | 9 | class SomeDataServiceStub implements SomeDataService { 10 | @Override 11 | public int[] retrieveAllData() { 12 | return new int[] { 1, 2, 3 }; 13 | } 14 | } 15 | 16 | class SomeDataServiceEmptyStub implements SomeDataService { 17 | @Override 18 | public int[] retrieveAllData() { 19 | return new int[] { }; 20 | } 21 | } 22 | 23 | class SomeDataServiceOneElementStub implements SomeDataService { 24 | @Override 25 | public int[] retrieveAllData() { 26 | return new int[] { 5 }; 27 | } 28 | } 29 | 30 | public class SomeBusinessStubTest { 31 | 32 | @Test 33 | public void calculateSumUsingDataService_basic() { 34 | SomeBusinessImpl business = new SomeBusinessImpl(); 35 | business.setSomeDataService(new SomeDataServiceStub()); 36 | int actualResult = business.calculateSumUsingDataService(); 37 | int expectedResult = 6; 38 | assertEquals(expectedResult, actualResult); 39 | } 40 | 41 | @Test 42 | public void calculateSumUsingDataService_empty() { 43 | SomeBusinessImpl business = new SomeBusinessImpl(); 44 | business.setSomeDataService(new SomeDataServiceEmptyStub()); 45 | int actualResult = business.calculateSumUsingDataService();//new int[] {} 46 | int expectedResult = 0; 47 | assertEquals(expectedResult, actualResult); 48 | } 49 | 50 | @Test 51 | public void calculateSumUsingDataService_oneValue() { 52 | SomeBusinessImpl business = new SomeBusinessImpl(); 53 | business.setSomeDataService(new SomeDataServiceOneElementStub()); 54 | int actualResult = business.calculateSumUsingDataService();//new int[] { 5 } 55 | int expectedResult = 5; 56 | assertEquals(expectedResult, actualResult); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/test/java/com/in28minutes/unittesting/unittesting/business/SomeBusinessTest.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.unittesting.unittesting.business; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | 8 | public class SomeBusinessTest { 9 | 10 | @Test 11 | public void calculateSum_basic() { 12 | SomeBusinessImpl business = new SomeBusinessImpl(); 13 | int actualResult = business.calculateSum(new int[] { 1,2,3}); 14 | int expectedResult = 6; 15 | assertEquals(expectedResult, actualResult); 16 | } 17 | 18 | @Test 19 | public void calculateSum_empty() { 20 | SomeBusinessImpl business = new SomeBusinessImpl(); 21 | int actualResult = business.calculateSum(new int[] { }); 22 | int expectedResult = 0; 23 | assertEquals(expectedResult, actualResult); 24 | } 25 | 26 | @Test 27 | public void calculateSum_oneValue() { 28 | SomeBusinessImpl business = new SomeBusinessImpl(); 29 | int actualResult = business.calculateSum(new int[] { 5}); 30 | int expectedResult = 5; 31 | assertEquals(expectedResult, actualResult); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/com/in28minutes/unittesting/unittesting/controller/HelloWorldControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.unittesting.unittesting.controller; 2 | 3 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 4 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 5 | 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.http.MediaType; 10 | import org.springframework.test.web.servlet.MockMvc; 11 | import org.springframework.test.web.servlet.MvcResult; 12 | import org.springframework.test.web.servlet.RequestBuilder; 13 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; 14 | 15 | @WebMvcTest(HelloWorldController.class) 16 | public class HelloWorldControllerTest { 17 | 18 | @Autowired 19 | private MockMvc mockMvc; 20 | 21 | @Test 22 | public void helloWorld_basic() throws Exception { 23 | //call GET "/hello-world" application/json 24 | 25 | RequestBuilder request = MockMvcRequestBuilders 26 | .get("/hello-world") 27 | .accept(MediaType.APPLICATION_JSON); 28 | 29 | MvcResult result = mockMvc.perform(request) 30 | .andExpect(status().isOk()) 31 | .andExpect(content().string("Hello World")) 32 | .andReturn(); 33 | 34 | //verify "Hello World" 35 | //assertEquals("Hello World", result.getResponse().getContentAsString()); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/com/in28minutes/unittesting/unittesting/controller/ItemControllerIT.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.unittesting.unittesting.controller; 2 | 3 | import org.json.JSONException; 4 | import org.junit.jupiter.api.Test; 5 | import org.skyscreamer.jsonassert.JSONAssert; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; 9 | import org.springframework.boot.test.web.client.TestRestTemplate; 10 | 11 | @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT) 12 | public class ItemControllerIT { 13 | 14 | @Autowired 15 | private TestRestTemplate restTemplate; 16 | 17 | @Test 18 | public void contextLoads() throws JSONException { 19 | 20 | String response = this.restTemplate.getForObject("/all-items-from-database", String.class); 21 | 22 | JSONAssert.assertEquals("[{id:10001},{id:10002},{id:10003}]", 23 | response, false); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/com/in28minutes/unittesting/unittesting/controller/ItemControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.unittesting.unittesting.controller; 2 | 3 | import static org.mockito.Mockito.when; 4 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 5 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 6 | 7 | import java.util.Arrays; 8 | 9 | import org.junit.jupiter.api.Test; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 12 | import org.springframework.boot.test.mock.mockito.MockBean; 13 | import org.springframework.http.MediaType; 14 | import org.springframework.test.web.servlet.MockMvc; 15 | import org.springframework.test.web.servlet.MvcResult; 16 | import org.springframework.test.web.servlet.RequestBuilder; 17 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; 18 | 19 | import com.in28minutes.unittesting.unittesting.business.ItemBusinessService; 20 | import com.in28minutes.unittesting.unittesting.model.Item; 21 | 22 | @WebMvcTest(ItemController.class) 23 | public class ItemControllerTest { 24 | 25 | @Autowired 26 | private MockMvc mockMvc; 27 | 28 | @MockBean 29 | private ItemBusinessService businessService; 30 | 31 | @Test 32 | public void dummyItem_basic() throws Exception { 33 | 34 | RequestBuilder request = MockMvcRequestBuilders 35 | .get("/dummy-item") 36 | .accept(MediaType.APPLICATION_JSON); 37 | 38 | MvcResult result = mockMvc.perform(request) 39 | .andExpect(status().isOk()) 40 | .andExpect(content().json("{\"id\": 1,\"name\":\"Ball\",\"price\":10,\"quantity\":100}")) 41 | .andReturn(); 42 | //JSONAssert.assertEquals(expected, result.getResponse().getContentAsString(), false); 43 | 44 | } 45 | 46 | @Test 47 | public void itemFromBusinessService_basic() throws Exception { 48 | when(businessService.retreiveHardcodedItem()).thenReturn( 49 | new Item(2,"Item2",10,10)); 50 | 51 | RequestBuilder request = MockMvcRequestBuilders 52 | .get("/item-from-business-service") 53 | .accept(MediaType.APPLICATION_JSON); 54 | 55 | MvcResult result = mockMvc.perform(request) 56 | .andExpect(status().isOk()) 57 | .andExpect(content().json("{id:2,name:Item2,price:10}")) 58 | .andReturn(); 59 | //JSONAssert.assertEquals(expected, result.getResponse().getContentAsString(), false); 60 | 61 | } 62 | 63 | @Test 64 | public void retrieveAllItems_basic() throws Exception { 65 | when(businessService.retrieveAllItems()).thenReturn( 66 | Arrays.asList(new Item(2,"Item2",10,10), 67 | new Item(3,"Item3",20,20)) 68 | ); 69 | 70 | RequestBuilder request = MockMvcRequestBuilders 71 | .get("/all-items-from-database") 72 | .accept(MediaType.APPLICATION_JSON); 73 | 74 | MvcResult result = mockMvc.perform(request) 75 | .andExpect(status().isOk()) 76 | .andExpect(content().json("[{id:3,name:Item3,price:20}, {id:2,name:Item2,price:10}]")) 77 | .andReturn(); 78 | //JSONAssert.assertEquals(expected, result.getResponse().getContentAsString(), false); 79 | 80 | } 81 | 82 | @Test 83 | public void retrieveAllItems_noitems() throws Exception { 84 | when(businessService.retrieveAllItems()).thenReturn( 85 | Arrays.asList() 86 | ); 87 | 88 | RequestBuilder request = MockMvcRequestBuilders 89 | .get("/all-items-from-database") 90 | .accept(MediaType.APPLICATION_JSON); 91 | 92 | MvcResult result = mockMvc.perform(request) 93 | .andExpect(status().isOk()) 94 | .andExpect(content().json("[]")) 95 | .andReturn(); 96 | //JSONAssert.assertEquals(expected, result.getResponse().getContentAsString(), false); 97 | 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/test/java/com/in28minutes/unittesting/unittesting/data/ItemRepositoryTest.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.unittesting.unittesting.data; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import java.util.List; 6 | 7 | import org.junit.jupiter.api.Test; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; 10 | 11 | import com.in28minutes.unittesting.unittesting.model.Item; 12 | 13 | @DataJpaTest 14 | public class ItemRepositoryTest { 15 | 16 | @Autowired 17 | private ItemRepository repository; 18 | 19 | @Test 20 | public void testFindAll() { 21 | List items = repository.findAll(); 22 | assertEquals(3,items.size()); 23 | } 24 | 25 | @Test 26 | public void testFindOne() { 27 | Item item = repository.findById(10001).get(); 28 | 29 | assertEquals("Item1",item.getName()); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/com/in28minutes/unittesting/unittesting/spike/AssertJTest.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.unittesting.unittesting.spike; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import java.util.Arrays; 6 | import java.util.List; 7 | 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class AssertJTest { 11 | 12 | @Test 13 | public void learning() { 14 | List numbers = Arrays.asList(12,15,45); 15 | 16 | //assertThat(numbers, hasSize(3)); 17 | assertThat(numbers).hasSize(3) 18 | .contains(12,15) 19 | .allMatch(x -> x > 10) 20 | .allMatch(x -> x < 100) 21 | .noneMatch(x -> x < 0); 22 | 23 | assertThat("").isEmpty(); 24 | assertThat("ABCDE").contains("BCD") 25 | .startsWith("ABC") 26 | .endsWith("CDE"); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/com/in28minutes/unittesting/unittesting/spike/HamcrestMatchersTest.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.unittesting.unittesting.spike; 2 | 3 | import static org.hamcrest.CoreMatchers.everyItem; 4 | import static org.hamcrest.CoreMatchers.hasItems; 5 | import static org.hamcrest.MatcherAssert.assertThat; 6 | import static org.hamcrest.Matchers.containsString; 7 | import static org.hamcrest.Matchers.endsWith; 8 | import static org.hamcrest.Matchers.greaterThan; 9 | import static org.hamcrest.Matchers.hasSize; 10 | import static org.hamcrest.Matchers.isEmptyString; 11 | import static org.hamcrest.Matchers.lessThan; 12 | import static org.hamcrest.Matchers.startsWith; 13 | 14 | import java.util.Arrays; 15 | import java.util.List; 16 | 17 | import org.junit.jupiter.api.Test; 18 | 19 | public class HamcrestMatchersTest { 20 | 21 | @Test 22 | public void learning() { 23 | List numbers = Arrays.asList(12,15,45); 24 | 25 | assertThat(numbers, hasSize(3)); 26 | assertThat(numbers, hasItems(12,45)); 27 | assertThat(numbers, everyItem(greaterThan(10))); 28 | assertThat(numbers, everyItem(lessThan(100))); 29 | 30 | assertThat("", isEmptyString()); 31 | assertThat("ABCDE", containsString("BCD")); 32 | assertThat("ABCDE", startsWith("ABC")); 33 | assertThat("ABCDE", endsWith("CDE")); 34 | 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/test/java/com/in28minutes/unittesting/unittesting/spike/JsonAssertTest.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.unittesting.unittesting.spike; 2 | 3 | import org.json.JSONException; 4 | import org.junit.jupiter.api.Test; 5 | import org.skyscreamer.jsonassert.JSONAssert; 6 | 7 | public class JsonAssertTest { 8 | 9 | String actualResponse = "{\"id\":1,\"name\":\"Ball\",\"price\":10,\"quantity\":100}"; 10 | 11 | @Test 12 | public void jsonAssert_StrictTrue_ExactMatchExceptForSpaces() throws JSONException { 13 | String expectedResponse = "{\"id\": 1, \"name\":\"Ball\", \"price\":10, \"quantity\":100}"; 14 | JSONAssert.assertEquals(expectedResponse, actualResponse, true); 15 | } 16 | 17 | @Test 18 | public void jsonAssert_StrictFalse() throws JSONException { 19 | String expectedResponse = "{\"id\": 1, \"name\":\"Ball\", \"price\":10}"; 20 | JSONAssert.assertEquals(expectedResponse, actualResponse, false); 21 | } 22 | 23 | @Test 24 | public void jsonAssert_WithoutEscapeCharacters() throws JSONException { 25 | String expectedResponse = "{id:1, name:Ball, price:10}"; 26 | JSONAssert.assertEquals(expectedResponse, actualResponse, false); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/com/in28minutes/unittesting/unittesting/spike/JsonPathTest.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.unittesting.unittesting.spike; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import java.util.List; 6 | 7 | import org.junit.jupiter.api.Test; 8 | 9 | import com.jayway.jsonpath.DocumentContext; 10 | import com.jayway.jsonpath.JsonPath; 11 | 12 | public class JsonPathTest { 13 | 14 | @Test 15 | public void learning() { 16 | String responseFromService = "[" + 17 | "{\"id\":10000, \"name\":\"Pencil\", \"quantity\":5}," + 18 | "{\"id\":10001, \"name\":\"Pen\", \"quantity\":15}," + 19 | "{\"id\":10002, \"name\":\"Eraser\", \"quantity\":10}" + 20 | "]"; 21 | 22 | DocumentContext context = JsonPath.parse(responseFromService); 23 | 24 | int length = context.read("$.length()"); 25 | assertThat(length).isEqualTo(3); 26 | 27 | List ids = context.read("$..id"); 28 | 29 | assertThat(ids).containsExactly(10000,10001,10002); 30 | 31 | System.out.println(context.read("$.[1]").toString()); 32 | System.out.println(context.read("$.[0:2]").toString()); 33 | System.out.println(context.read("$.[?(@.name=='Eraser')]").toString()); 34 | System.out.println(context.read("$.[?(@.quantity==5)]").toString()); 35 | 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/test/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.jpa.show-sql=false 2 | spring.h2.console.enabled=false -------------------------------------------------------------------------------- /starting-code.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | ## Complete Code Example 6 | 7 | ### /src/main/java/com/in28minutes/springunittestingwithmockito/business/ItemService.java 8 | 9 | ```java 10 | package com.in28minutes.springunittestingwithmockito.business; 11 | 12 | import java.util.List; 13 | 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.stereotype.Component; 16 | 17 | import com.in28minutes.springunittestingwithmockito.data.ItemRepository; 18 | import com.in28minutes.springunittestingwithmockito.entity.Item; 19 | 20 | @Component 21 | public class ItemService { 22 | 23 | @Autowired 24 | private ItemRepository repository; 25 | 26 | public List calculateTotalValue() { 27 | 28 | List items = repository.findAll(); 29 | 30 | items.stream().forEach((item) -> { 31 | item.setValue(item.getPrice() * item.getQuantity()); 32 | }); 33 | 34 | return items; 35 | } 36 | 37 | public void insertItem() { 38 | 39 | } 40 | 41 | } 42 | ``` 43 | --- 44 | 45 | ### /src/main/java/com/in28minutes/springunittestingwithmockito/business/SomeBusinessService.java 46 | 47 | ```java 48 | package com.in28minutes.springunittestingwithmockito.business; 49 | 50 | import java.util.Arrays; 51 | 52 | import com.in28minutes.springunittestingwithmockito.data.SomeDataService; 53 | 54 | public class SomeBusinessService { 55 | 56 | private SomeDataService someData; 57 | 58 | public SomeBusinessService(SomeDataService someData) { 59 | super(); 60 | this.someData = someData; 61 | } 62 | 63 | public int calculateSum() { 64 | return Arrays.stream(someData.retrieveData()) 65 | .reduce(Integer::sum).orElse(0); 66 | } 67 | } 68 | ``` 69 | --- 70 | 71 | ### /src/main/java/com/in28minutes/springunittestingwithmockito/controller/ItemController.java 72 | 73 | ```java 74 | package com.in28minutes.springunittestingwithmockito.controller; 75 | 76 | import java.util.List; 77 | 78 | import org.springframework.beans.factory.annotation.Autowired; 79 | import org.springframework.web.bind.annotation.GetMapping; 80 | import org.springframework.web.bind.annotation.RestController; 81 | 82 | import com.in28minutes.springunittestingwithmockito.business.ItemService; 83 | import com.in28minutes.springunittestingwithmockito.entity.Item; 84 | 85 | @RestController 86 | public class ItemController { 87 | 88 | @Autowired 89 | private ItemService service; 90 | 91 | @GetMapping("/items") 92 | public List retrieveAllItems() { 93 | return service.calculateTotalValue(); 94 | } 95 | 96 | } 97 | ``` 98 | --- 99 | 100 | ### /src/main/java/com/in28minutes/springunittestingwithmockito/data/ItemRepository.java 101 | 102 | ```java 103 | package com.in28minutes.springunittestingwithmockito.data; 104 | 105 | import org.springframework.data.jpa.repository.JpaRepository; 106 | 107 | import com.in28minutes.springunittestingwithmockito.entity.Item; 108 | 109 | public interface ItemRepository extends JpaRepository{ 110 | 111 | } 112 | ``` 113 | --- 114 | 115 | ### /src/main/java/com/in28minutes/springunittestingwithmockito/data/SomeDataService.java 116 | 117 | ```java 118 | package com.in28minutes.springunittestingwithmockito.data; 119 | 120 | public class SomeDataService { 121 | public int[] retrieveData() { 122 | throw new RuntimeException("Unimplemented"); 123 | } 124 | } 125 | ``` 126 | --- 127 | 128 | ### /src/main/java/com/in28minutes/springunittestingwithmockito/entity/Item.java 129 | 130 | ```java 131 | package com.in28minutes.springunittestingwithmockito.entity; 132 | 133 | import javax.persistence.Entity; 134 | import javax.persistence.Id; 135 | import javax.persistence.Transient; 136 | 137 | @Entity 138 | public class Item { 139 | @Id 140 | private long id; 141 | private String name; 142 | private int quantity; 143 | private int price; 144 | 145 | @Transient 146 | private long value; 147 | 148 | public Item() { 149 | 150 | } 151 | 152 | public Item(int id, String name, int quantity, int price) { 153 | super(); 154 | this.id = id; 155 | this.name = name; 156 | this.quantity = quantity; 157 | this.price = price; 158 | } 159 | 160 | public long getId() { 161 | return id; 162 | } 163 | 164 | public void setId(long id) { 165 | this.id = id; 166 | } 167 | 168 | public String getName() { 169 | return name; 170 | } 171 | 172 | public void setName(String name) { 173 | this.name = name; 174 | } 175 | 176 | public int getQuantity() { 177 | return quantity; 178 | } 179 | 180 | public void setQuantity(int quantity) { 181 | this.quantity = quantity; 182 | } 183 | 184 | public int getPrice() { 185 | return price; 186 | } 187 | 188 | public void setPrice(int price) { 189 | this.price = price; 190 | } 191 | 192 | public long getValue() { 193 | return value; 194 | } 195 | 196 | public void setValue(long value) { 197 | this.value = value; 198 | } 199 | 200 | } 201 | ``` 202 | --- 203 | 204 | ### /src/main/java/com/in28minutes/springunittestingwithmockito/SpringUnitTestingWithMockitoApplication.java 205 | 206 | ```java 207 | package com.in28minutes.springunittestingwithmockito; 208 | 209 | import org.springframework.boot.SpringApplication; 210 | import org.springframework.boot.autoconfigure.SpringBootApplication; 211 | 212 | @SpringBootApplication 213 | public class SpringUnitTestingWithMockitoApplication { 214 | 215 | public static void main(String[] args) { 216 | SpringApplication.run(SpringUnitTestingWithMockitoApplication.class, args); 217 | } 218 | } 219 | ``` 220 | --- 221 | 222 | ### /src/main/resources/application.properties 223 | 224 | ```properties 225 | spring.h2.console.enabled=true 226 | spring.jpa.show-sql=true 227 | ``` 228 | --- 229 | 230 | ### /src/main/resources/data.sql 231 | 232 | ``` 233 | insert into item (id, name, quantity, price) values(10001, 'Chocolates', 25, 2); 234 | insert into item (id, name, quantity, price) values(10002, 'Biscuits', 50, 2); 235 | insert into item (id, name, quantity, price) values(10003, 'Pens', 25, 3); 236 | insert into item (id, name, quantity, price) values(10004, 'Pencils', 25, 2); 237 | ``` 238 | --- 239 | 240 | ### /src/test/java/com/in28minutes/springunittestingwithmockito/AssertjTest.java 241 | 242 | ```java 243 | package com.in28minutes.springunittestingwithmockito; 244 | 245 | import static org.assertj.core.api.Assertions.assertThat; 246 | 247 | import java.util.Arrays; 248 | import java.util.List; 249 | 250 | import org.junit.Test; 251 | 252 | public class AssertjTest { 253 | 254 | @Test 255 | public void basicHamcrestMatchers() { 256 | //List 257 | List scores = Arrays.asList(99, 100, 101, 105); 258 | 259 | assertThat(scores).hasSize(4); 260 | assertThat(scores).contains(100, 101); 261 | assertThat(scores).allMatch(x -> x > 90); 262 | assertThat(scores).allMatch(x -> x < 200); 263 | 264 | // String 265 | assertThat("").isEmpty(); 266 | 267 | // Array 268 | Integer[] marks = { 1, 2, 3 }; 269 | 270 | assertThat(marks).hasSize(3); 271 | assertThat(marks).contains(2, 3, 1); 272 | 273 | } 274 | } 275 | ``` 276 | --- 277 | 278 | ### /src/test/java/com/in28minutes/springunittestingwithmockito/business/ItemServiceTest.java 279 | 280 | ```java 281 | package com.in28minutes.springunittestingwithmockito.business; 282 | 283 | import static org.junit.Assert.assertEquals; 284 | import static org.mockito.Mockito.when; 285 | 286 | import java.util.ArrayList; 287 | import java.util.Arrays; 288 | import java.util.List; 289 | 290 | import org.junit.Test; 291 | import org.junit.runner.RunWith; 292 | import org.mockito.InjectMocks; 293 | import org.mockito.Mock; 294 | import org.mockito.junit.MockitoJUnitRunner; 295 | 296 | import com.in28minutes.springunittestingwithmockito.data.ItemRepository; 297 | import com.in28minutes.springunittestingwithmockito.entity.Item; 298 | 299 | @RunWith(MockitoJUnitRunner.class) 300 | public class ItemServiceTest { 301 | 302 | @Mock 303 | ItemRepository repository; 304 | 305 | @InjectMocks 306 | ItemService service; 307 | 308 | @Test 309 | public void testWithMock_usingMockitoRunner() { 310 | List mockList = Arrays.asList(new Item(1, "Dummy", 10, 5)); 311 | 312 | when(repository.findAll()).thenReturn(mockList); 313 | 314 | List items = service.calculateTotalValue(); 315 | assertEquals(50,items.get(0).getValue()); 316 | } 317 | } 318 | ``` 319 | --- 320 | 321 | ### /src/test/java/com/in28minutes/springunittestingwithmockito/business/SomeBusinessServiceTest.java 322 | 323 | ```java 324 | package com.in28minutes.springunittestingwithmockito.business; 325 | 326 | import static org.junit.Assert.assertEquals; 327 | import static org.mockito.Mockito.mock; 328 | import static org.mockito.Mockito.when; 329 | 330 | import org.junit.Test; 331 | import org.junit.runner.RunWith; 332 | import org.mockito.InjectMocks; 333 | import org.mockito.Mock; 334 | import org.mockito.junit.MockitoJUnitRunner; 335 | 336 | import com.in28minutes.springunittestingwithmockito.data.SomeDataService; 337 | 338 | @RunWith(MockitoJUnitRunner.class) 339 | public class SomeBusinessServiceTest { 340 | 341 | @Mock 342 | SomeDataService dataService; 343 | 344 | @InjectMocks 345 | SomeBusinessService businessService; 346 | 347 | @Test(expected=Exception.class) 348 | public void testWithExpectedException() { 349 | SomeDataService dataService = new SomeDataService(); 350 | SomeBusinessService businessService = 351 | new SomeBusinessService(dataService); 352 | businessService.calculateSum(); 353 | } 354 | 355 | @Test 356 | public void testWithMock() { 357 | SomeDataService dataService = mock(SomeDataService.class); 358 | when(dataService.retrieveData()).thenReturn(new int[] {10,20}); 359 | SomeBusinessService businessService = 360 | new SomeBusinessService(dataService); 361 | assertEquals(30,businessService.calculateSum()); 362 | } 363 | 364 | @Test 365 | public void playWithListClass() { 366 | 367 | } 368 | 369 | @Test 370 | public void testWithMock_usingMockitoRunner() { 371 | when(dataService.retrieveData()).thenReturn(new int[] {10,20}); 372 | assertEquals(30,businessService.calculateSum()); 373 | } 374 | 375 | @Test 376 | public void mockitoRunnerUnderstandSpringAutowiringToo() { 377 | 378 | } 379 | } 380 | ``` 381 | --- 382 | 383 | ### /src/test/java/com/in28minutes/springunittestingwithmockito/controller/ItemControllerIT.java 384 | 385 | ```java 386 | package com.in28minutes.springunittestingwithmockito.controller; 387 | 388 | import static org.assertj.core.api.Assertions.assertThat; 389 | 390 | import org.junit.Test; 391 | import org.junit.runner.RunWith; 392 | import org.springframework.beans.factory.annotation.Autowired; 393 | import org.springframework.boot.test.context.SpringBootTest; 394 | import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; 395 | import org.springframework.boot.test.web.client.TestRestTemplate; 396 | import org.springframework.test.context.junit4.SpringRunner; 397 | 398 | @RunWith(SpringRunner.class) 399 | @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) 400 | public class ItemControllerIT { 401 | 402 | @Autowired 403 | private TestRestTemplate restTemplate; 404 | 405 | @Test 406 | public void exampleTest2() { 407 | String body = this.restTemplate.getForObject("/items", String.class); 408 | assertThat(body).contains("Pencil"); 409 | } 410 | } 411 | ``` 412 | --- 413 | 414 | ### /src/test/java/com/in28minutes/springunittestingwithmockito/controller/ItemControllerTest.java 415 | 416 | ```java 417 | package com.in28minutes.springunittestingwithmockito.controller; 418 | 419 | import static org.mockito.Mockito.when; 420 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 421 | 422 | import java.util.Arrays; 423 | import java.util.List; 424 | 425 | import org.junit.Test; 426 | import org.junit.runner.RunWith; 427 | import org.skyscreamer.jsonassert.JSONAssert; 428 | import org.springframework.beans.factory.annotation.Autowired; 429 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 430 | import org.springframework.boot.test.mock.mockito.MockBean; 431 | import org.springframework.http.MediaType; 432 | import org.springframework.test.context.junit4.SpringRunner; 433 | import org.springframework.test.web.servlet.MockMvc; 434 | import org.springframework.test.web.servlet.MvcResult; 435 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; 436 | 437 | import com.in28minutes.springunittestingwithmockito.business.ItemService; 438 | import com.in28minutes.springunittestingwithmockito.entity.Item; 439 | 440 | @RunWith(SpringRunner.class) 441 | @WebMvcTest(value = ItemController.class) 442 | public class ItemControllerTest { 443 | 444 | @Autowired 445 | private MockMvc mvc; 446 | 447 | @MockBean 448 | private ItemService service; 449 | 450 | @Test 451 | public void retrieveItems() throws Exception { 452 | List mockList = Arrays.asList(new Item(1, "Dummy", 10, 5)); 453 | when(service.calculateTotalValue()).thenReturn(mockList); 454 | MvcResult result = mvc.perform(MockMvcRequestBuilders.get("/items").accept(MediaType.APPLICATION_JSON)) 455 | .andExpect(status().isOk()).andReturn(); 456 | String expected = "[" + "{id:1,name:Dummy}" + "]"; 457 | JSONAssert.assertEquals(expected, result.getResponse().getContentAsString(), false); 458 | } 459 | } 460 | ``` 461 | --- 462 | 463 | ### /src/test/java/com/in28minutes/springunittestingwithmockito/data/ItemRepositoryTest.java 464 | 465 | ```java 466 | package com.in28minutes.springunittestingwithmockito.data; 467 | 468 | import static org.assertj.core.api.Assertions.assertThat; 469 | 470 | import java.util.List; 471 | 472 | import org.junit.Test; 473 | import org.junit.runner.RunWith; 474 | import org.springframework.beans.factory.annotation.Autowired; 475 | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; 476 | import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; 477 | import org.springframework.test.context.junit4.SpringRunner; 478 | 479 | import com.in28minutes.springunittestingwithmockito.entity.Item; 480 | 481 | @RunWith(SpringRunner.class) 482 | @DataJpaTest 483 | public class ItemRepositoryTest { 484 | 485 | @Autowired 486 | private TestEntityManager entityManager; 487 | 488 | @Autowired 489 | private ItemRepository repository; 490 | 491 | @Test 492 | public void testExample() throws Exception { 493 | List items = this.repository.findAll(); 494 | assertThat(items.size()).isEqualTo(4); 495 | } 496 | 497 | } 498 | ``` 499 | --- 500 | 501 | ### /src/test/java/com/in28minutes/springunittestingwithmockito/HamcrestMatcherTest.java 502 | 503 | ```java 504 | package com.in28minutes.springunittestingwithmockito; 505 | 506 | import static org.hamcrest.CoreMatchers.hasItems; 507 | import static org.hamcrest.MatcherAssert.assertThat; 508 | import static org.hamcrest.Matchers.arrayContainingInAnyOrder; 509 | import static org.hamcrest.Matchers.arrayWithSize; 510 | import static org.hamcrest.Matchers.greaterThan; 511 | import static org.hamcrest.Matchers.hasSize; 512 | import static org.hamcrest.Matchers.isEmptyString; 513 | import static org.hamcrest.Matchers.lessThan; 514 | import static org.hamcrest.core.Every.everyItem; 515 | 516 | import java.util.Arrays; 517 | import java.util.List; 518 | 519 | import org.junit.Test; 520 | 521 | public class HamcrestMatcherTest { 522 | 523 | @Test 524 | public void basicHamcrestMatchers() { 525 | 526 | //List 527 | List scores = Arrays.asList(99, 100, 101, 105); 528 | assertThat(scores, hasSize(4)); 529 | assertThat(scores, hasItems(100, 101)); 530 | assertThat(scores, everyItem(greaterThan(90))); 531 | assertThat(scores, everyItem(lessThan(200))); 532 | 533 | // String 534 | assertThat("", isEmptyString()); 535 | 536 | // Array 537 | Integer[] marks = { 1, 2, 3 }; 538 | 539 | assertThat(marks, arrayWithSize(3)); 540 | assertThat(marks, arrayContainingInAnyOrder(2, 3, 1)); 541 | 542 | } 543 | } 544 | ``` 545 | --- 546 | 547 | ### /src/test/java/com/in28minutes/springunittestingwithmockito/JsonAssertTest.java 548 | 549 | ```java 550 | package com.in28minutes.springunittestingwithmockito; 551 | 552 | import org.json.JSONException; 553 | import org.junit.Test; 554 | import org.skyscreamer.jsonassert.JSONAssert; 555 | 556 | public class JsonAssertTest { 557 | @Test 558 | public void jsonAssertTest() throws JSONException { 559 | String responseFromService = "[{\"id\":10001,\"name\":\"Chocolates\",\"quantity\":25,\"price\":2,\"value\":50}," 560 | + "{\"id\":10002,\"name\":\"Biscuits\",\"quantity\":50,\"price\":2,\"value\":100}," 561 | + "{\"id\":10003,\"name\":\"Pens\",\"quantity\":25,\"price\":3,\"value\":75}," 562 | + "{\"id\":10004,\"name\":\"Pencils\",\"quantity\":25,\"price\":2,\"value\":50}]"; 563 | 564 | JSONAssert.assertEquals("[{id:10004,name:Pencils},{},{},{}]", responseFromService, false); 565 | 566 | // Strict true 567 | // 1. Checks all elements 568 | // 2. Order in arrays becomes important 569 | 570 | // Easy to read error messages 571 | } 572 | 573 | } 574 | ``` 575 | --- 576 | 577 | ### /src/test/java/com/in28minutes/springunittestingwithmockito/JsonPathTest.java 578 | 579 | ```java 580 | package com.in28minutes.springunittestingwithmockito; 581 | 582 | import static org.assertj.core.api.Assertions.assertThat; 583 | 584 | import java.util.List; 585 | 586 | import org.junit.Test; 587 | 588 | import com.jayway.jsonpath.JsonPath; 589 | import com.jayway.jsonpath.ReadContext; 590 | 591 | public class JsonPathTest { 592 | @Test 593 | public void jsonAssertTest() { 594 | String responseFromService = "[{\"id\":10001,\"name\":\"Chocolates\",\"quantity\":25,\"price\":2,\"value\":50}," 595 | + "{\"id\":10002,\"name\":\"Biscuits\",\"quantity\":50,\"price\":2,\"value\":100}," 596 | + "{\"id\":10003,\"name\":\"Pens\",\"quantity\":25,\"price\":3,\"value\":75}," 597 | + "{\"id\":10004,\"name\":\"Pencils\",\"quantity\":25,\"price\":2,\"value\":50}]"; 598 | 599 | ReadContext ctx = JsonPath.parse(responseFromService); 600 | 601 | List allIds = ctx.read("$..id"); 602 | assertThat(allIds).containsExactly(10001,10002,10003,10004); 603 | System.out.println(ctx.read("$.length()]").toString()); 604 | System.out.println(ctx.read("$.[2]").toString()); 605 | System.out.println(ctx.read("$.[0:2]").toString());//0 inclusive 2 exclusive 606 | System.out.println(ctx.read("$[?(@.quantity==50)]").toString()); 607 | } 608 | 609 | } 610 | ``` 611 | --- 612 | 613 | ### /src/test/java/com/in28minutes/springunittestingwithmockito/ListTest.java 614 | 615 | ```java 616 | package com.in28minutes.springunittestingwithmockito; 617 | 618 | import static org.junit.Assert.assertEquals; 619 | import static org.junit.Assert.assertNull; 620 | import static org.mockito.Mockito.mock; 621 | import static org.mockito.Mockito.when; 622 | 623 | import java.util.List; 624 | 625 | import org.junit.Test; 626 | import org.mockito.Mockito; 627 | 628 | public class ListTest { 629 | 630 | @Test 631 | public void letsMockListSize() { 632 | List list = mock(List.class); 633 | when(list.size()).thenReturn(10); 634 | assertEquals(10, list.size()); 635 | } 636 | 637 | @Test 638 | public void letsMockListSizeWithMultipleReturnValues() { 639 | List list = mock(List.class); 640 | when(list.size()).thenReturn(10).thenReturn(20); 641 | assertEquals(10, list.size()); // First Call 642 | assertEquals(20, list.size()); // Second Call 643 | } 644 | 645 | @Test 646 | public void letsMockListGet() { 647 | List list = mock(List.class); 648 | when(list.get(0)).thenReturn("in28Minutes"); 649 | assertEquals("in28Minutes", list.get(0)); 650 | assertNull(list.get(1)); 651 | } 652 | 653 | @Test(expected = RuntimeException.class) 654 | public void letsMockListGetToThrowException() { 655 | List list = mock(List.class); 656 | when(list.get(Mockito.anyInt())).thenThrow( 657 | new RuntimeException("Something went wrong")); 658 | list.get(0); 659 | } 660 | 661 | @Test 662 | public void letsMockListGetWithAny() { 663 | List list = mock(List.class); 664 | Mockito.when(list.get(Mockito.anyInt())).thenReturn("in28Minutes"); 665 | // If you are using argument matchers, all arguments 666 | // have to be provided by matchers. 667 | assertEquals("in28Minutes", list.get(0)); 668 | assertEquals("in28Minutes", list.get(1)); 669 | } 670 | } 671 | ``` 672 | --- 673 | 674 | ### /src/test/java/com/in28minutes/springunittestingwithmockito/SpringUnitTestingWithMockitoApplicationTests.java 675 | 676 | ```java 677 | package com.in28minutes.springunittestingwithmockito; 678 | 679 | import static org.mockito.Mockito.when; 680 | 681 | import java.util.ArrayList; 682 | import java.util.List; 683 | 684 | import org.junit.Test; 685 | import org.junit.runner.RunWith; 686 | import org.springframework.beans.factory.annotation.Autowired; 687 | import org.springframework.boot.test.context.SpringBootTest; 688 | import org.springframework.boot.test.mock.mockito.MockBean; 689 | import org.springframework.test.context.junit4.SpringRunner; 690 | 691 | import com.in28minutes.springunittestingwithmockito.business.ItemService; 692 | import com.in28minutes.springunittestingwithmockito.data.ItemRepository; 693 | import com.in28minutes.springunittestingwithmockito.entity.Item; 694 | 695 | @RunWith(SpringRunner.class) 696 | @SpringBootTest 697 | public class SpringUnitTestingWithMockitoApplicationTests { 698 | 699 | @MockBean 700 | ItemRepository repository; 701 | 702 | @Autowired 703 | ItemService service; 704 | 705 | @Test 706 | public void contextLoads() { 707 | List asList = new ArrayList(); 708 | asList.add(new Item(1, "Dummy", 10, 5)); 709 | 710 | when(repository.findAll()).thenReturn(asList); 711 | 712 | System.out.println(service.calculateTotalValue()); 713 | } 714 | 715 | } 716 | ``` 717 | --- 718 | --------------------------------------------------------------------------------