diff --git a/.gitignore b/.gitignore index 200bfbe2..a9e7e666 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,7 @@ Thumbs.db .project .classpath .idea +.mvn *.iml atlassian-ide-plugin.xml target diff --git a/pom.xml b/pom.xml index 30247811..10d045f8 100644 --- a/pom.xml +++ b/pom.xml @@ -32,6 +32,34 @@ org.springframework.boot spring-boot-starter-web + + + org.springframework.boot + spring-boot-devtools + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + com.h2database + h2 + runtime + + + + + org.webjars + bootstrap + 3.3.5 + + + org.webjars + jquery + 2.1.4 + org.springframework.boot diff --git a/src/main/java/guru/springframework/SpringmvcApplication.java b/src/main/java/guru/springframework/SpringmvcApplication.java index b3a27dd9..d73706cb 100644 --- a/src/main/java/guru/springframework/SpringmvcApplication.java +++ b/src/main/java/guru/springframework/SpringmvcApplication.java @@ -2,11 +2,18 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ApplicationContext; @SpringBootApplication public class SpringmvcApplication { public static void main(String[] args) { - SpringApplication.run(SpringmvcApplication.class, args); + ApplicationContext ctx = SpringApplication.run(SpringmvcApplication.class, args); + +// for (String name : ctx.getBeanDefinitionNames()){ +// System.out.println(name); +// } +// System.out.println("******* Bean Count *******"); +// System.out.println(ctx.getBeanDefinitionCount()); } } diff --git a/src/main/java/guru/springframework/controllers/CustomerController.java b/src/main/java/guru/springframework/controllers/CustomerController.java new file mode 100644 index 00000000..5b835c0c --- /dev/null +++ b/src/main/java/guru/springframework/controllers/CustomerController.java @@ -0,0 +1,61 @@ +package guru.springframework.controllers; + +import guru.springframework.domain.Customer; +import guru.springframework.services.CustomerService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +/** + * Created by jt on 11/15/15. + */ +@RequestMapping("/customer") +@Controller +public class CustomerController { + + private CustomerService customerService; + + @Autowired + public void setCustomerService(CustomerService customerService) { + this.customerService = customerService; + } + + @RequestMapping({"/list", "/"}) + public String listCustomers(Model model){ + model.addAttribute("customers", customerService.listAll()); + return "customer/list"; + } + + @RequestMapping("/show/{id}") + public String showCustomer(@PathVariable Integer id, Model model){ + model.addAttribute("customer", customerService.getById(id)); + return "customer/show"; + } + + @RequestMapping("/edit/{id}") + public String edit(@PathVariable Integer id, Model model){ + model.addAttribute("customer", customerService.getById(id)); + return "customer/customerform"; + } + + @RequestMapping("/new") + public String newCustomer(Model model){ + model.addAttribute("customer", new Customer()); + return "customer/customerform"; + } + + @RequestMapping(method = RequestMethod.POST) + public String saveOrUpdate(Customer customer){ + Customer newCustomer = customerService.saveOrUpdate(customer); + return "redirect:customer/show/" + newCustomer.getId(); + } + + @RequestMapping("/delete/{id}") + public String delete(@PathVariable Integer id){ + customerService.delete(id); + return "redirect:/customer/list"; + } +} diff --git a/src/main/java/guru/springframework/controllers/IndexController.java b/src/main/java/guru/springframework/controllers/IndexController.java new file mode 100644 index 00000000..4bbb072b --- /dev/null +++ b/src/main/java/guru/springframework/controllers/IndexController.java @@ -0,0 +1,16 @@ +package guru.springframework.controllers; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * Created by jt on 11/6/15. + */ +@Controller +public class IndexController { + + @RequestMapping({"/", ""}) + public String index(){ + return "index"; + } +} diff --git a/src/main/java/guru/springframework/controllers/ProductController.java b/src/main/java/guru/springframework/controllers/ProductController.java new file mode 100644 index 00000000..4c60ff50 --- /dev/null +++ b/src/main/java/guru/springframework/controllers/ProductController.java @@ -0,0 +1,60 @@ +package guru.springframework.controllers; + +import guru.springframework.domain.Product; +import guru.springframework.services.ProductService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +/** + * Created by jt on 11/6/15. + */ +@Controller +public class ProductController { + + private ProductService productService; + + @Autowired + public void setProductService(ProductService productService) { + this.productService = productService; + } + + @RequestMapping("/product/list") + public String listProducts(Model model){ + model.addAttribute("products", productService.listAll()); + return "product/list"; + } + + @RequestMapping("/product/show/{id}") + public String getProduct(@PathVariable Integer id, Model model){ + model.addAttribute("product", productService.getById(id)); + return "product/show"; + } + + @RequestMapping("product/edit/{id}") + public String edit(@PathVariable Integer id, Model model){ + model.addAttribute("product", productService.getById(id)); + return "product/productform"; + } + + @RequestMapping("/product/new") + public String newProduct(Model model){ + model.addAttribute("product", new Product()); + return "product/productform"; + } + + @RequestMapping(value = "/product", method = RequestMethod.POST) + public String saveOrUpdateProduct(Product product){ + Product savedProduct = productService.saveOrUpdate(product); + return "redirect:/product/show/" + savedProduct.getId(); + } + + @RequestMapping("/product/delete/{id}") + public String delete(@PathVariable Integer id){ + productService.delete(id); + return "redirect:/product/list"; + } +} diff --git a/src/main/java/guru/springframework/domain/Customer.java b/src/main/java/guru/springframework/domain/Customer.java new file mode 100644 index 00000000..cd53347e --- /dev/null +++ b/src/main/java/guru/springframework/domain/Customer.java @@ -0,0 +1,100 @@ +package guru.springframework.domain; + +/** + * Created by jt on 11/14/15. + */ +public class Customer implements DomainObject { + + private Integer id; + private String firstName; + private String lastName; + private String email; + private String phoneNumber; + private String addressLine1; + private String addressLine2; + private String city; + private String state; + private String zipCode; + + @Override + public Integer getId() { + return id; + } + + @Override + public void setId(Integer id) { + this.id = id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPhoneNumber() { + return phoneNumber; + } + + public void setPhoneNumber(String phoneNumber) { + this.phoneNumber = phoneNumber; + } + + public String getAddressLine1() { + return addressLine1; + } + + public void setAddressLine1(String addressLine1) { + this.addressLine1 = addressLine1; + } + + public String getAddressLine2() { + return addressLine2; + } + + public void setAddressLine2(String addressLine2) { + this.addressLine2 = addressLine2; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } + + public String getZipCode() { + return zipCode; + } + + public void setZipCode(String zipCode) { + this.zipCode = zipCode; + } +} diff --git a/src/main/java/guru/springframework/domain/DomainObject.java b/src/main/java/guru/springframework/domain/DomainObject.java new file mode 100644 index 00000000..5744c4e7 --- /dev/null +++ b/src/main/java/guru/springframework/domain/DomainObject.java @@ -0,0 +1,11 @@ +package guru.springframework.domain; + +/** + * Created by jt on 11/14/15. + */ +public interface DomainObject { + + Integer getId(); + + void setId(Integer id); +} diff --git a/src/main/java/guru/springframework/domain/Product.java b/src/main/java/guru/springframework/domain/Product.java new file mode 100644 index 00000000..ffadb179 --- /dev/null +++ b/src/main/java/guru/springframework/domain/Product.java @@ -0,0 +1,62 @@ +package guru.springframework.domain; + +import javax.persistence.*; +import java.math.BigDecimal; + +/** + * Created by jt on 11/6/15. + */ +@Entity +public class Product implements DomainObject{ + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Integer id; + + @Version + private Integer version; + + private String description; + private BigDecimal price; + private String imageUrl; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public Integer getVersion() { + return version; + } + + public void setVersion(Integer version) { + this.version = version; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public BigDecimal getPrice() { + return price; + } + + public void setPrice(BigDecimal price) { + this.price = price; + } + + public String getImageUrl() { + return imageUrl; + } + + public void setImageUrl(String imageUrl) { + this.imageUrl = imageUrl; + } +} diff --git a/src/main/java/guru/springframework/services/AbstractMapService.java b/src/main/java/guru/springframework/services/AbstractMapService.java new file mode 100644 index 00000000..1e21261e --- /dev/null +++ b/src/main/java/guru/springframework/services/AbstractMapService.java @@ -0,0 +1,50 @@ +package guru.springframework.services; + +import guru.springframework.domain.DomainObject; + +import java.util.*; + +/** + * Created by jt on 11/14/15. + */ +public abstract class AbstractMapService { + protected Map domainMap; + + public AbstractMapService() { + domainMap = new HashMap<>(); + loadDomainObjects(); + } + + public List listAll() { + return new ArrayList<>(domainMap.values()); + } + + public DomainObject getById(Integer id) { + return domainMap.get(id); + } + + public DomainObject saveOrUpdate(DomainObject domainObject) { + if (domainObject != null){ + + if (domainObject.getId() == null){ + domainObject.setId(getNextKey()); + } + domainMap.put(domainObject.getId(), domainObject); + + return domainObject; + } else { + throw new RuntimeException("Object Can't be null"); + } + } + + public void delete(Integer id) { + domainMap.remove(id); + } + + private Integer getNextKey(){ + return Collections.max(domainMap.keySet()) + 1; + } + + protected abstract void loadDomainObjects(); + +} diff --git a/src/main/java/guru/springframework/services/CRUDService.java b/src/main/java/guru/springframework/services/CRUDService.java new file mode 100644 index 00000000..7355d122 --- /dev/null +++ b/src/main/java/guru/springframework/services/CRUDService.java @@ -0,0 +1,16 @@ +package guru.springframework.services; + +import java.util.List; + +/** + * Created by jt on 11/14/15. + */ +public interface CRUDService { + List listAll(); + + T getById(Integer id); + + T saveOrUpdate(T domainObject); + + void delete(Integer id); +} diff --git a/src/main/java/guru/springframework/services/CustomerService.java b/src/main/java/guru/springframework/services/CustomerService.java new file mode 100644 index 00000000..441b15bd --- /dev/null +++ b/src/main/java/guru/springframework/services/CustomerService.java @@ -0,0 +1,10 @@ +package guru.springframework.services; + +import guru.springframework.domain.Customer; + +/** + * Created by jt on 11/14/15. + */ +public interface CustomerService extends CRUDService{ + +} diff --git a/src/main/java/guru/springframework/services/CustomerServiceImpl.java b/src/main/java/guru/springframework/services/CustomerServiceImpl.java new file mode 100644 index 00000000..c86adce5 --- /dev/null +++ b/src/main/java/guru/springframework/services/CustomerServiceImpl.java @@ -0,0 +1,77 @@ +package guru.springframework.services; + +import guru.springframework.domain.Customer; +import guru.springframework.domain.DomainObject; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.List; + +/** + * Created by jt on 11/14/15. + */ +@Service +public class CustomerServiceImpl extends AbstractMapService implements CustomerService { + + @Override + public List listAll() { + return super.listAll(); + } + + @Override + public Customer getById(Integer id) { + return (Customer) super.getById(id); + } + + @Override + public Customer saveOrUpdate(Customer domainObject) { + return (Customer) super.saveOrUpdate(domainObject); + } + + @Override + public void delete(Integer id) { + super.delete(id); + } + + @Override + protected void loadDomainObjects() { + domainMap = new HashMap<>(); + + Customer customer1 = new Customer(); + customer1.setId(1); + customer1.setFirstName("Micheal"); + customer1.setLastName("Weston"); + customer1.setAddressLine1("1 Main St"); + customer1.setCity("Miami"); + customer1.setState("Florida"); + customer1.setZipCode("33101"); + customer1.setEmail("micheal@burnnotice.com"); + customer1.setPhoneNumber("305.333.0101"); + + Customer customer2 = new Customer(); + customer2.setId(2); + customer2.setFirstName("Fiona"); + customer2.setLastName("Glenanne"); + customer2.setAddressLine1("1 Key Biscane Ave"); + customer2.setCity("Miami"); + customer2.setState("Florida"); + customer2.setZipCode("33101"); + customer2.setEmail("fiona@burnnotice.com"); + customer2.setPhoneNumber("305.323.0233"); + + Customer customer3 = new Customer(); + customer3.setId(3); + customer3.setFirstName("Sam"); + customer3.setLastName("Axe"); + customer3.setAddressLine1("1 Little Cuba Road"); + customer3.setCity("Miami"); + customer3.setState("Florida"); + customer3.setZipCode("33101"); + customer3.setEmail("sam@burnnotice.com"); + customer3.setPhoneNumber("305.426.9832"); + + domainMap.put(1, customer1); + domainMap.put(2, customer2); + domainMap.put(3, customer3); + } +} diff --git a/src/main/java/guru/springframework/services/ProductService.java b/src/main/java/guru/springframework/services/ProductService.java new file mode 100644 index 00000000..62a35310 --- /dev/null +++ b/src/main/java/guru/springframework/services/ProductService.java @@ -0,0 +1,10 @@ +package guru.springframework.services; + +import guru.springframework.domain.Product; + +/** + * Created by jt on 11/6/15. + */ +public interface ProductService extends CRUDService { + +} diff --git a/src/main/java/guru/springframework/services/ProductServiceImpl.java b/src/main/java/guru/springframework/services/ProductServiceImpl.java new file mode 100644 index 00000000..1382aad2 --- /dev/null +++ b/src/main/java/guru/springframework/services/ProductServiceImpl.java @@ -0,0 +1,80 @@ +package guru.springframework.services; + +import guru.springframework.domain.DomainObject; +import guru.springframework.domain.Product; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.List; + +/** + * Created by jt on 11/6/15. + */ +@Service +public class ProductServiceImpl extends AbstractMapService implements ProductService { + + @Override + public List listAll() { + return super.listAll(); + } + + @Override + public Product getById(Integer id) { + return (Product) super.getById(id); + } + + @Override + public Product saveOrUpdate(Product domainObject) { + return (Product) super.saveOrUpdate(domainObject); + } + + @Override + public void delete(Integer id) { + super.delete(id); + } + + protected void loadDomainObjects(){ + domainMap = new HashMap<>(); + + Product product1 = new Product(); + product1.setId(1); + product1.setDescription("Product 1"); + product1.setPrice(new BigDecimal("12.99")); + product1.setImageUrl("http://example.com/product1"); + + domainMap.put(1, product1); + + Product product2 = new Product(); + product2.setId(2); + product2.setDescription("Product 2"); + product2.setPrice(new BigDecimal("14.99")); + product2.setImageUrl("http://example.com/product2"); + + domainMap.put(2, product2); + + Product product3 = new Product(); + product3.setId(3); + product3.setDescription("Product 3"); + product3.setPrice(new BigDecimal("34.99")); + product3.setImageUrl("http://example.com/product3"); + + domainMap.put(3, product3); + + Product product4 = new Product(); + product4.setId(4); + product4.setDescription("Product 4"); + product4.setPrice(new BigDecimal("44.99")); + product4.setImageUrl("http://example.com/product4"); + + domainMap.put(4, product4); + + Product product5 = new Product(); + product5.setId(5); + product5.setDescription("Product 2"); + product5.setPrice(new BigDecimal("25.99")); + product5.setImageUrl("http://example.com/product5"); + + domainMap.put(5, product5); + } +} diff --git a/src/main/resources/static/css/spring-core.css b/src/main/resources/static/css/spring-core.css new file mode 100644 index 00000000..e69de29b diff --git a/src/main/resources/templates/customer/customerform.html b/src/main/resources/templates/customer/customerform.html new file mode 100644 index 00000000..c3b6fe1a --- /dev/null +++ b/src/main/resources/templates/customer/customerform.html @@ -0,0 +1,86 @@ + + + + Spring Core Online Tutorial - Customer Form + + + + + + + + + +
+ +

Customer Details

+
+
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/templates/customer/list.html b/src/main/resources/templates/customer/list.html new file mode 100644 index 00000000..4904641b --- /dev/null +++ b/src/main/resources/templates/customer/list.html @@ -0,0 +1,50 @@ + + + + Spring Core Online Tutorial - List Customers + + + + + + + + + +
+
+

Customer List

+ + + + + + + + + + + + + + + + + + + +
IdFirst NameLast NameEmailShowEditDelete
View Edit Delete
+
+
+ +
+
+ + + \ No newline at end of file diff --git a/src/main/resources/templates/customer/show.html b/src/main/resources/templates/customer/show.html new file mode 100644 index 00000000..5dadfa44 --- /dev/null +++ b/src/main/resources/templates/customer/show.html @@ -0,0 +1,94 @@ + + + + Spring Core Online Tutorial - Show Customer + + + + + + + + + +
+ +
+
+

Show Customer

+
+
+
+
+
+
+ +
+

Customer Id

+
+
+
+ +
+

First Name

+
+
+
+ +
+

Last Name

+
+
+
+ +
+

Email

+
+
+
+ +
+

Phone

+
+
+
+ +
+

Address Line 1

+
+
+
+ +
+

Address Line 2

+
+
+
+ +
+

City

+
+
+
+ +
+

State

+
+
+
+ +
+

Zipcode

+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html new file mode 100644 index 00000000..9622d970 --- /dev/null +++ b/src/main/resources/templates/index.html @@ -0,0 +1,32 @@ + + + + + Spring Core Online Tutorial + + + + + + + + + +
+

Hello World

+ +

This is my Thymeleaf index page.

+ + + +
+ + + \ No newline at end of file diff --git a/src/main/resources/templates/product/list.html b/src/main/resources/templates/product/list.html new file mode 100644 index 00000000..b7ca555c --- /dev/null +++ b/src/main/resources/templates/product/list.html @@ -0,0 +1,50 @@ + + + + Spring Core Online Tutorial - List Products + + + + + + + + + +
+
+

Product List

+ + + + + + + + + + + + + + + + + + + +
IdDescriptionPriceImage URLListEditDelete
View Edit Delete
+
+
+ +
+
+ + + \ No newline at end of file diff --git a/src/main/resources/templates/product/productform.html b/src/main/resources/templates/product/productform.html new file mode 100644 index 00000000..cd9d9b6e --- /dev/null +++ b/src/main/resources/templates/product/productform.html @@ -0,0 +1,50 @@ + + + + Spring Core Online Tutorial - Product Form + + + + + + + + + +
+ +

Product Details

+
+
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/templates/product/show.html b/src/main/resources/templates/product/show.html new file mode 100644 index 00000000..069ea3c9 --- /dev/null +++ b/src/main/resources/templates/product/show.html @@ -0,0 +1,58 @@ + + + + Spring Core Online Tutorial - Show Product + + + + + + + + + +
+ +
+
+

Show Product

+
+
+
+
+
+
+ +
+

Product Id

+
+
+
+ +
+

Description

+
+
+
+ +
+

Price

+
+
+
+ +
+

Image

+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/test/java/guru/springframework/controllers/CustomerControllerTest.java b/src/test/java/guru/springframework/controllers/CustomerControllerTest.java new file mode 100644 index 00000000..db23e3c3 --- /dev/null +++ b/src/test/java/guru/springframework/controllers/CustomerControllerTest.java @@ -0,0 +1,159 @@ +package guru.springframework.controllers; + +import guru.springframework.domain.Customer; +import guru.springframework.services.CustomerService; +import org.junit.Before; +import org.junit.Test; +import org.mockito.*; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import java.util.ArrayList; +import java.util.List; + +import static org.hamcrest.Matchers.*; +import static org.hamcrest.beans.HasPropertyWithValue.hasProperty; +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +/** + * Created by jt on 11/17/15. + */ +public class CustomerControllerTest { + + @Mock + private CustomerService customerService; + + @InjectMocks + private CustomerController customerController; + + private MockMvc mockMvc; + + @Before + public void setup(){ + MockitoAnnotations.initMocks(this); + + mockMvc = MockMvcBuilders.standaloneSetup(customerController).build(); + } + + @Test + public void testList() throws Exception{ + List customers = new ArrayList<>(); + customers.add(new Customer()); + customers.add(new Customer()); + + when(customerService.listAll()).thenReturn((List) customers); + + mockMvc.perform(get("/customer/list")) + .andExpect(status().isOk()) + .andExpect(view().name("customer/list")) + .andExpect(model().attribute("customers", hasSize(2))); + } + + @Test + public void testShow() throws Exception { + Integer id = 1; + + when(customerService.getById(id)).thenReturn(new Customer()); + + mockMvc.perform(get("/customer/show/1")) + .andExpect(status().isOk()) + .andExpect(view().name("customer/show")) + .andExpect(model().attribute("customer", instanceOf(Customer.class))); + } + + @Test + public void testEdit() throws Exception { + Integer id = 1; + + when(customerService.getById(id)).thenReturn(new Customer()); + + mockMvc.perform(get("/customer/edit/1")) + .andExpect(status().isOk()) + .andExpect(view().name("customer/customerform")) + .andExpect(model().attribute("customer", instanceOf(Customer.class))); + } + + @Test + public void testNewCustomer() throws Exception { + verifyZeroInteractions(customerService); + + mockMvc.perform(get("/customer/new")) + .andExpect(status().isOk()) + .andExpect(view().name("customer/customerform")) + .andExpect(model().attribute("customer", instanceOf(Customer.class))); + } + + @Test + public void testSaveOrUpdate() throws Exception { + Integer id = 1; + Customer returnCustomer = new Customer(); + String firstName = "Micheal"; + String lastName = "Weston"; + String addressLine1 = "1 Main St"; + String addressLine2 = "Apt 301"; + String city = "Miami"; + String state = "Florida"; + String zipCode = "33101"; + String email = "micheal@burnnotice.com"; + String phoneNumber = "305.333.0101"; + + returnCustomer.setId(id); + returnCustomer.setFirstName(firstName); + returnCustomer.setLastName(lastName); + returnCustomer.setAddressLine1(addressLine1); + returnCustomer.setAddressLine2(addressLine2); + returnCustomer.setCity(city); + returnCustomer.setState(state); + returnCustomer.setZipCode(zipCode); + returnCustomer.setEmail(email); + returnCustomer.setPhoneNumber(phoneNumber); + + when(customerService.saveOrUpdate(Matchers.any())).thenReturn(returnCustomer); + + mockMvc.perform(post("/customer") + .param("id", "1") + .param("firstName", firstName) + .param("lastName", lastName) + .param("addressLine1", addressLine1) + .param("addressLine2", addressLine2) + .param("city", city) + .param("state", state) + .param("zipCode", zipCode) + .param("email", email) + .param("phoneNumber", phoneNumber)) + .andExpect(status().is3xxRedirection()) + .andExpect(view().name("redirect:customer/show/1")) + .andExpect(model().attribute("customer", instanceOf(Customer.class))) + .andExpect(model().attribute("customer", hasProperty("firstName", is(firstName)))) + .andExpect(model().attribute("customer", hasProperty("lastName", is(lastName)))) + .andExpect(model().attribute("customer", hasProperty("addressLine1", is(addressLine1)))) + .andExpect(model().attribute("customer", hasProperty("addressLine2", is(addressLine2)))) + .andExpect(model().attribute("customer", hasProperty("city", is(city)))) + .andExpect(model().attribute("customer", hasProperty("state", is(state)))) + .andExpect(model().attribute("customer", hasProperty("zipCode", is(zipCode)))) + .andExpect(model().attribute("customer", hasProperty("email", is(email)))) + .andExpect(model().attribute("customer", hasProperty("phoneNumber", is(phoneNumber)))); + + ArgumentCaptor customerCaptor = ArgumentCaptor.forClass(Customer.class); + verify(customerService).saveOrUpdate(customerCaptor.capture()); + + Customer boundCustomer = customerCaptor.getValue(); + + assertEquals(id, boundCustomer.getId()); + assertEquals(firstName, boundCustomer.getFirstName()); + assertEquals(lastName, boundCustomer.getLastName()); + assertEquals(addressLine1, boundCustomer.getAddressLine1()); + assertEquals(addressLine2, boundCustomer.getAddressLine2()); + assertEquals(city, boundCustomer.getCity()); + assertEquals(state, boundCustomer.getState()); + assertEquals(zipCode, boundCustomer.getZipCode()); + assertEquals(email, boundCustomer.getEmail()); + assertEquals(phoneNumber, boundCustomer.getPhoneNumber()); + + + } +} diff --git a/src/test/java/guru/springframework/controllers/IndexControllerTest.java b/src/test/java/guru/springframework/controllers/IndexControllerTest.java new file mode 100644 index 00000000..a1ee14b1 --- /dev/null +++ b/src/test/java/guru/springframework/controllers/IndexControllerTest.java @@ -0,0 +1,35 @@ +package guru.springframework.controllers; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; + +/** + * Created by jt on 11/16/15. + */ +public class IndexControllerTest { + + private MockMvc mockMvc; + + private IndexController indexController; + + @Before + public void setup(){ + indexController = new IndexController(); + mockMvc = MockMvcBuilders.standaloneSetup(indexController).build(); + + } + + @Test + public void testIndex() throws Exception{ + mockMvc.perform(get("/")) + .andExpect(status().isOk()) + .andExpect(view().name("indexdd")); + } + +} diff --git a/src/test/java/guru/springframework/controllers/ProductControllerTest.java b/src/test/java/guru/springframework/controllers/ProductControllerTest.java new file mode 100644 index 00000000..278a96d6 --- /dev/null +++ b/src/test/java/guru/springframework/controllers/ProductControllerTest.java @@ -0,0 +1,144 @@ +package guru.springframework.controllers; + +import guru.springframework.domain.Product; +import guru.springframework.services.ProductService; +import org.junit.Before; +import org.junit.Test; +import org.mockito.*; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; +/** + * Created by jt on 11/16/15. + */ +public class ProductControllerTest { + + @Mock //Mockito Mock object + private ProductService productService; + + @InjectMocks //setups up controller, and injects mock objects into it. + private ProductController productController; + + private MockMvc mockMvc; + + @Before + public void setup(){ + MockitoAnnotations.initMocks(this); //initilizes controller and mocks + + mockMvc = MockMvcBuilders.standaloneSetup(productController).build(); + } + + @Test + public void testList() throws Exception{ + + List products = new ArrayList<>(); + products.add(new Product()); + products.add(new Product()); + + //specific Mockito interaction, tell stub to return list of products + when(productService.listAll()).thenReturn((List) products); //need to strip generics to keep Mockito happy. + + mockMvc.perform(get("/product/list")) + .andExpect(status().isOk()) + .andExpect(view().name("product/list")) + .andExpect(model().attribute("products", hasSize(2))); + } + + @Test + public void testShow() throws Exception{ + Integer id = 1; + + //Tell Mockito stub to return new product for ID 1 + when(productService.getById(id)).thenReturn(new Product()); + + mockMvc.perform(get("/product/show/1")) + .andExpect(status().isOk()) + .andExpect(view().name("product/show")) + .andExpect(model().attribute("product", instanceOf(Product.class))); + } + + @Test + public void testEdit() throws Exception{ + Integer id = 1; + + //Tell Mockito stub to return new product for ID 1 + when(productService.getById(id)).thenReturn(new Product()); + + mockMvc.perform(get("/product/edit/1")) + .andExpect(status().isOk()) + .andExpect(view().name("product/productform")) + .andExpect(model().attribute("product", instanceOf(Product.class))); + } + + @Test + public void testNewProduct() throws Exception { + Integer id = 1; + + //should not call service + verifyZeroInteractions(productService); + + mockMvc.perform(get("/product/new")) + .andExpect(status().isOk()) + .andExpect(view().name("product/productform")) + .andExpect(model().attribute("product", instanceOf(Product.class))); + } + + @Test + public void testSaveOrUpdate() throws Exception { + Integer id = 1; + String description = "Test Description"; + BigDecimal price = new BigDecimal("12.00"); + String imageUrl = "example.com"; + + Product returnProduct = new Product(); + returnProduct.setId(id); + returnProduct.setDescription(description); + returnProduct.setPrice(price); + returnProduct.setImageUrl(imageUrl); + + when(productService.saveOrUpdate(Matchers.any())).thenReturn(returnProduct); + + mockMvc.perform(post("/product") + .param("id", "1") + .param("description", description) + .param("price", "12.00") + .param("imageUrl", "example.com")) + .andExpect(status().is3xxRedirection()) + .andExpect(view().name("redirect:/product/show/1")) + .andExpect(model().attribute("product", instanceOf(Product.class))) + .andExpect(model().attribute("product", hasProperty("id", is(id)))) + .andExpect(model().attribute("product", hasProperty("description", is(description)))) + .andExpect(model().attribute("product", hasProperty("price", is(price)))) + .andExpect(model().attribute("product", hasProperty("imageUrl", is(imageUrl)))); + + //verify properties of bound object + ArgumentCaptor boundProduct = ArgumentCaptor.forClass(Product.class); + verify(productService).saveOrUpdate(boundProduct.capture()); + + assertEquals(id, boundProduct.getValue().getId()); + assertEquals(description, boundProduct.getValue().getDescription()); + assertEquals(price, boundProduct.getValue().getPrice()); + assertEquals(imageUrl, boundProduct.getValue().getImageUrl()); + } + + @Test + public void testDelete() throws Exception{ + Integer id = 1; + + mockMvc.perform(get("/product/delete/1")) + .andExpect(status().is3xxRedirection()) + .andExpect(view().name("redirect:/product/list")); + + verify(productService, times(1)).delete(id); + } +}