package net.safedata.springboot.training.d03s03;

import net.safedata.springboot.training.d03s03.model.Product;
import net.safedata.springboot.training.d03s03.repository.ProductRepository;
import net.safedata.springboot.training.d03s03.service.ProductService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.*;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class ProductServiceTest {

    @Mock
    private ProductRepository productRepository;

    // the tested service; also called 'system under test'
    @InjectMocks
    private ProductService productService;

    @Test
    //public void shouldGetProductsWhenThereAreAvailableProducts() {
    public void givenThereAreAvailableProducts_whenRetrievingProducts_thenProductsAreRetrievedCorrectly() {
        // arrange
        final List<Product> products = Arrays.asList(
                new Product(1, "Asus"),
                new Product(2, "Dell")
        );
        when(productRepository.findAll()).thenReturn(products);

        // act
        final List<Product> resulted = productService.getProducts();

        // assert
        assertNotNull(resulted);
        assertThat(resulted.size(), is(products.size()));
    }

    @Test
    public void shouldNotGetAnyProductsWhenThereAreNoAvailableProducts() {
        when(productRepository.findAll()).thenReturn(new ArrayList<>());

        final List<Product> resulted = productService.getProducts();

        assertThat(resulted.size(), is(0));
    }

    @Test
    public void shouldGetAProductByIdWhenTheProductExists() {
        Product product = mock(Product.class);
        final String mockedName = "mocked name";
        when(product.getName()).thenReturn(mockedName);
        when(product.getId()).thenReturn(20);

        when(productRepository.findOne(anyInt())).thenReturn(product);

        final Product resulted = productService.getProduct(25);

        assertNotNull(resulted);
        assertThat(resulted.getName(), is(mockedName));
        assertThat(resulted.getId(), not(0));
    }

    @Test(expected = IllegalArgumentException.class)
    public void shouldGetAProductByIdWhenTheProductDoesNotExist() {
        when(productRepository.findOne(anyInt())).thenReturn(null);

        productService.getProduct(13);
    }

    @Test
    public void shouldSaveAProduct() {
        Product product = mock(Product.class);
        final String mockedName = "mocked name";
        when(product.getName()).thenReturn(mockedName);

        final String response = productService.saveProduct(product);

        verify(productRepository, times(1)).save(product);

        assertNotNull(response);
        assertThat(response.length(), not(0));
    }
}

@@ -816,16 +816,66 @@
 ository;
+ // the collaborator (productRepository) is mocked
 %0A%0A    //
@@ -1002,77 +1002,8 @@
 est%0A
-    //public void shouldGetProductsWhenThereAreAvailableProducts() %7B%0A
     
@@ -1124,16 +1124,50 @@
  arrange
+, including mocking behavior setup
 %0A       
@@ -1370,24 +1370,88 @@
 ts);
-%0A%0A        // act
+ // simple mocking example%0A%0A        // act --%3E calling the tested service method
 %0A   
@@ -1534,16 +1534,97 @@
 / assert
+ --%3E verifying the response of the tested method is correct (by the requirements)
 %0A       
@@ -1744,31 +1744,60 @@
 oid 
-shouldNotGetAny
+givenThereAreNoAvailableProducts_thenGetting
 Products
 When
@@ -1796,39 +1796,34 @@
 ucts
-WhenThereAreNoAvailableProducts
+_thenNoProductsAreReturned
 () %7B
@@ -1959,32 +1959,65 @@
 getProducts();%0A%0A
+        assertNotNull(resulted);%0A
         assertTh
@@ -2073,33 +2073,69 @@
 public void 
-shouldGet
+givenThereAreAvailableProducts_whenRetrieving
 AProductById
@@ -2126,33 +2126,34 @@
 vingAProductById
-W
+_t
 henTheProductExi
@@ -2153,14 +2153,19 @@
 duct
-Exists
+IsRetrieved
 () %7B
@@ -2716,17 +2716,52 @@
 oid 
-shouldGet
+givenThereAreNoAvailableProducts_whenGetting
 APro
@@ -2772,34 +2772,47 @@
 ById
-WhenTheProductDoesNotExist
+_thenAnIllegalArgumentExceptionIsThrown
 () %7B
@@ -2957,26 +2957,123 @@
 oid 
-shouldSaveAProduct
+givenAProductIsSaved_whenSavingTheProduct_thenSaveIsCalledOneTimesAndTheResponseShouldNotBeEmptyOrNull%0A            
 () %7B
@@ -3073,32 +3073,38 @@
    () %7B%0A        
+final 
 Product product 
@@ -3294,32 +3294,146 @@
 duct(product);%0A%0A
+        // it verifies that the .save method (from the productRepository collaborator) was called exactly 1 times%0A
         verify(p

Use GWT naming for all test methods, added a few comments