This class is in the top of my tests hierarchy:
@TestPropertySource("/test.properties")
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public abstract class ApplicationAbstractTest {
}
And few more test classes:
@WebAppConfiguration
@ActiveProfiles("mysql")
abstract public class AbstractControllerTest extends ApplicationAbstractTest {
protected MockMvc mockMvc;
@Autowired
private WebApplicationContext webApplicationContext;
@PostConstruct
private void postConstruct() {
mockMvc = MockMvcBuilders
.webAppContextSetup(webApplicationContext)
.apply(springSecurity())
.build();
}
}
JsonUserServiceTest:
@ActiveProfiles("json")
public class JsonUserServiceTest extends ApplicationAbstractTest {
@Before
public void setUp() throws Exception {
...
}
}
ContactControllerTest:
public class ContactControllerTest extends AbstractControllerTest {
@Test
public void testGet() throws Exception {
mockMvc.perform(get("/update-" + ID + "-contact")
.with(userAuth(USER)))
// .andExpect(status().isOk())
.andDo(print())
.andExpect(view().name("details"))
.andExpect(forwardedUrl("/WEB-INF/jsp/details.jsp"));
}
}
So, when I run ContactControllerTest
along - it is successfull, and print
method shows me:
Handler:
Type = com.telecom.web.ContactController
Method = public java.lang.String com.myApp.web.ContactController.details(java.lang.Integer,org.springframework.ui.ModelMap)
But when I run all tests, so JsonUserServiceTest
runs first, ContactControllerTest
fails. And print
shows:
Handler:
Type = null
...
java.lang.AssertionError: No ModelAndView found
What is wrong in configuration? Or how troubleshoot it?
UPD: at the same time, test like this, allways works fine:
public class UserControllerTest extends AbstractControllerTest {
@Test
public void testRegister() throws Exception {
mockMvc.perform(get("/register"))
.andDo(print())
.andExpect(view().name("profile"))
.andExpect(forwardedUrl("/WEB-INF/jsp/profile.jsp"));
}
}
UPD: There is controller's method I'm testing:
@GetMapping("/update-{id}-contact")
public String details(@PathVariable Integer id, ModelMap model) {
Integer userId = AuthorizedUser.id();
LOG.info("get contact {} for User {}", id, userId);
Contact contact = service.get(id, userId);
model.addAttribute("contact", contact);
return "details";
}
I also have such bean:
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/jsp/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
UPD: I've tried configure mockMvc in separate class:
@Configuration
public class TestConfig {
@Autowired
private WebApplicationContext webApplicationContext;
@Bean
public MockMvc mockMvc() {
return MockMvcBuilders
.webAppContextSetup(webApplicationContext)
.apply(springSecurity())
.build();
}
}
And added it here:
@WebAppConfiguration
@ContextConfiguration(classes = {TestConfig.class})
@ActiveProfiles("mysql")
abstract public class AbstractControllerTest extends ApplicationAbstractTest {
but I've received:
java.lang.IllegalStateException: springSecurityFilterChain cannot be null. Ensure a Bean with the name springSecurityFilterChain implementing Filter is present or inject the Filter to be used.
The WARN message doesn't cause the test cases to fail. It just says that Entity manager factory is registered twice. This will only be an issue if you cluster your application using the same Entity Manager Factory. For test case run it is not a cause for concern.
The root cause of the testcase failure is in these two lines
.andExpect(view().name("details"))
.andExpect(forwardedUrl("/WEB-INF/jsp/details.jsp"));
Please check if the project has a view named "details" and the forwardded url is "/WEB-INF/jsp/details.jsp"
Update
Could you please try this
@Configuration
public class TestConfig {
@Autowired
private Filter springSecurityFilterChain;
@Autowired
private WebApplicationContext webApplicationContext;
@Bean
public MockMvc mockMvc() {
return MockMvcBuilders
.webAppContextSetup(webApplicationContext)
.apply(springSecurityFilterChain)
.build();
}
}
Create a configuration file that will initialize mocking objects for your test cases. And put at all test case classes.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {TestConfig.class})
It will initialize all your mocking objects only once and cached after that and reused for all test cases.
Or if you don't want to use mocking configuration, you can directly pass the actual application configuration to ContextConfiguration as below
For annotation based application configuration (here AppConfig and AppConfig2 are your configuration class)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {AppConfig.class, AppConfig2.class})
For xml based application configuration (here appConfig.xml and appConfig2.xml are your configuration files)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:pathTo/appConfig.xml","classpath:pathTo/appConfig2.xml"})
Reference : JUnit + Spring integration example
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With