data.xml file. You need to change 3 to 4 in the package name org.springframework.orm.hibernate4 , remove the configLocation and configurationClass parameters in the configLocation and instead add the packagesToScan parameter where to transfer the list of class packages with Hibernate mapping from hibernate.cfg.xml . This file itself can be deleted, we no longer need it. As a result, the sessionfactory bin takes the form: <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="packagesToScan"> <list> <value>net.schastny.contactmanager.domain</value> <value>com.acme.contactmanager.domain</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.hbm2ddl.auto">create-drop</prop> <prop key="hibernate.dialect">${jdbc.dialect}</prop> <prop key="hibernate.connection.charSet">UTF-8</prop> </props> </property> </bean> src/test/resources directory, copy security.xml security.xml settings into it, and create testdb.properties property file for the database. You can do without it, but again, for educational purposes, we will see how you can set properties in bins from the outside. File contents db.user.name=sa db.user.pass= log4j.xml and with resources on it all. Go to the source code.src/test/groovy , package com.acme.contactmanager.testIn order for the maven to find our grooves when building from the command line, we’ll add build-helper-maven-plugin to pom.xml
TestConfig.groovy @Configuration @ComponentScan(['net.schastny.contactmanager.dao', 'com.acme.contactmanager.dao', 'net.schastny.contactmanager.web', 'net.schastny.contactmanager.service']) @PropertySource('classpath:testdb.properties') @ImportResource('classpath:security.xml') @EnableTransactionManagement class TestConfig { // ... } testdb.propertiessecurity.xmlBy the way, about the transaction. We have interfaces and implementations for the DAO and service classes, but in general we can confine ourselves to the implementation class alone. In this case, the annotation will need to specify that the proxyTarget is created automatically, otherwise there will be problems: @EnableTransactionManagement(proxyTargetClass = true)testdb.properties to class attributes using @Value class TestConfig { @Value('${db.user.name}') String userName @Value('${db.user.pass}') String userPass // ... } LocalSessionFactoryBean , where we will use the properties obtained. Here we see the packagesToScan already familiar to us. @Bean public LocalSessionFactoryBean sessionFactory() { LocalSessionFactoryBean bean = new LocalSessionFactoryBean() bean.packagesToScan = [ 'com.acme.contactmanager.domain', 'net.schastny.contactmanager.domain'] as String[] Properties props = new Properties() props."hibernate.connection.driver_class" = "org.h2.Driver" props."hibernate.connection.url" = "jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE;DB_CLOSE_ON_EXIT=FALSE" props."hibernate.connection.username" = userName props."hibernate.connection.password" = userPass props."hibernate.dialect" = "org.hibernate.dialect.H2Dialect" props."hibernate.hbm2ddl.auto" = "create-drop" props."hibernate.temp.use_jdbc_metadata_defaults" = "false" bean.hibernateProperties = props bean } This hibernate.temp.use_jdbc_metadata_defaults = false thing helps when it slows down the context to retrieve metadata from the databaseHibernateTransactionManager @Bean public HibernateTransactionManager transactionManager() { HibernateTransactionManager txManager = new HibernateTransactionManager() txManager.autodetectDataSource = false txManager.sessionFactory = sessionFactory().object txManager } MockMvcTest.groovy @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration(classes = [ TestConfig.class ] ) class MockMvcTest { @Autowired WebApplicationContext wac MockMvc mockMvc @Before public void setup() { this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).dispatchOptions(true).build() } } home() method is a good candidate for the test case, where there is a simple redirect @RequestMapping("/") public String home() { return "redirect:/index"; } @Test public void home() { MockHttpServletRequestBuilder request = MockMvcRequestBuilders.get("/") ResultActions result = mockMvc.perform(request) result.andExpect(MockMvcResultMatchers.redirectedUrl("/index")) } TheandExpect()function provides great opportunities for checking the result obtained, here are examples from Javadoc, which give a general idea of its work:mockMvc.perform(get("/person/1")) .andExpect(status.isOk()) .andExpect(content().mimeType(MediaType.APPLICATION_JSON)) .andExpect(jsonPath("$.person.name").equalTo("Jason")); mockMvc.perform(post("/form")) .andExpect(status.isOk()) .andExpect(redirectedUrl("/person/1")) .andExpect(model().size(1)) .andExpect(model().attributeExists("person")) .andExpect(flash().attributeCount(1)) .andExpect(flash().attribute("message", "success!"));
@RequestMapping("/index") public String listContacts(Map<String, Object> map) { map.put("contact", new Contact()); map.put("contactList", contactService.listContact()); map.put("contactTypeList", contactService.listContactType()); return "contact"; } @Test public void index() { ResultActions result = mockMvc.perform(MockMvcRequestBuilders.get("/index")) result.andExpect(MockMvcResultMatchers.view().name("contact")) .andExpect(MockMvcResultMatchers.model().attributeExists("contact")) .andExpect(MockMvcResultMatchers.model().attributeExists("contactList")) .andExpect(MockMvcResultMatchers.model().attributeExists("contactTypeList")) } MvcResult mvcResult = result.andReturn() assert mvcResult.modelAndView.model.contactTypeList.size() == 3 @RequestMapping(value = "/add", method = RequestMethod.POST) public String addContact(@ModelAttribute("contact") Contact contact, BindingResult result) { contactService.addContact(contact); return "redirect:/index"; } @ModelAttribute Contact contact parameter. But it is not all that bad. A quick googling request for “mockmvc Model Attribute” here gives the result . Such mapping can simply be replaced by a set of query parameters. The function of adding parameters to the query is quite expected to look like this: param(Stirng name, String... values) . We write @Autowired ContactService contactService @Test public void add() { // , def contacts = contactService.listContact() assert !contacts // def contactTypes = contactService.listContactType() assert contactTypes // POST-, mockMvc.perform(MockMvcRequestBuilders.post("/add") .param("firstname",'firstname') .param("lastname",'lastname') .param("email",'firstname.lastname@gmail.com') .param("telephone",'555-1234') .param("contacttype.id", contactTypes[0].id.toString()) .andExpect(MockMvcResultMatchers.redirectedUrl("/index")) // contacts = contactService.listContact() // id assert contacts assert contacts[0].id // , contactService.removeContact(contacts[0].id) } @RequestMapping("/delete/{contactId}") public String deleteContact(@PathVariable("contactId") Integer contactId) { contactService.removeContact(contactId); return "redirect:/index"; } @PathVariable also not a problem, just add it to the URL. @Test public void delete() { // def contactTypes = contactService.listContactType() assert contactTypes Contact contact = new Contact( firstname : 'firstname', lastname : 'lastname', email : 'firstname.lastname@gmail.com', telephone : '555-1234', contacttype : contactTypes[0] ) contactService.addContact(contact) assert contact.id def contacts = contactService.listContact() // contacts.id id assert contact.id in contacts.id // POST- , URL id // ${contact.id} - placeholder, GString! mockMvc.perform(MockMvcRequestBuilders.get("/delete/${contact.id}") .andExpect(MockMvcResultMatchers.redirectedUrl("/index")) // , def contacts = contactService.listContact() assert !(contact.id in contacts.id) } security.xml if there is no mention of users and roles in the tests? And he will be right. In the third part of the lesson, we will add support for working with SpringSecurity.addFilter() , in which we can pass an instance of springSecurityFilterChain . Let's change our test as follows: @Autowired FilterChainProxy springSecurityFilterChain @Before public void setup() { this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac) .addFilter(springSecurityFilterChain) // .dispatchOptions(true).build() } List<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList("ROLE_USER"); Authentication auth = new UsernamePasswordAuthenticationToken("user1", "1111", authorities); SecurityContextHolder.getContext().setAuthentication(auth); DEBUG: org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /add; Attributes: [ROLE_USER] DEBUG: org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication. AnonymousAuthenticationToken@d4551ca6: Principal: guest; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication. WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS DEBUG: org.springframework.security.web.access.ExceptionTranslationFilter - Access is denied (user is anonymous); redirecting to authentication entry point Granted Authorities: ROLE_ANONYMOUS hints that our feint didn’t work with our ears. But I hasten to reassure - our guilt is not here, supporting Security in the tests has not yet been implemented . That is why in the beginning I wrote that integration with SpringSecurity is “almost no problem”. The problem is still there, but it is solved.src/test/java folder and show how it can be used for our needs.setAuthentication(auth) , which turned out to be useless, and in the add () method we add one line to the query construct: //... mockMvc.perform(MockMvcRequestBuilders.post("/add") .param("firstname",'firstname') .param("lastname",'lastname') .param("email",'firstname.lastname@gmail.com') .param("telephone",'555-1234') .param("contacttype.id", contactTypes[0].id.toString()) .with(SecurityRequestPostProcessors.userDetailsService("user1"))) // Security .andExpect(MockMvcResultMatchers.redirectedUrl("/index")) // ... Granted Authorities: ROLE_USER result.andExpect(MockMvcResultMatchers.redirectedUrl("http://localhost/login.jsp")) mockMvc.perform(MockMvcRequestBuilders.get("/delete/1") .with(SecurityRequestPostProcessors.userDetailsService("user1"))) .andExpect(MockMvcResultMatchers.forwardedUrl("/error403.jsp")) Source: https://habr.com/ru/post/171911/
All Articles