Nitesh kumar
Nitesh kumar

Reputation: 376

Testing spring mvc controller

I am testing my controller using mockito junit framework.

I got stuck in the controller layer where I get null pointer exception in UserDetails interface.

I tried to override the interface but still I face the problem.

This is my default controller only for userDetails interface to get the user information.

public class DefaultController {


    public UserDetails getUserDetails(){
        UserDetails userDetails=null;
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (!(auth instanceof AnonymousAuthenticationToken)) {
               userDetails = (UserDetails) auth.getPrincipal();
        }
        return userDetails;
    }

    public Set<Integer> getUserCSRoles(){
        Set<Integer> csroles=new HashSet<Integer>();
        UserDetails userDetails=getUserDetails();
        if(userDetails!=null)
        for (GrantedAuthority grantedAuthority : userDetails.getAuthorities()) {
            if(grantedAuthority.getAuthority().split("_").length>1){
            if(grantedAuthority.getAuthority().split("_")[1].toString().equalsIgnoreCase("MANAGER")){
                csroles.add(1);
            }else if(grantedAuthority.getAuthority().split("_")[1].toString().equalsIgnoreCase("SHAREDSERVICE")){
                csroles.add(2);
            }else if(grantedAuthority.getAuthority().split("_")[1].toString().equalsIgnoreCase("ADMIN")){
                csroles.add(3);
            }else if(grantedAuthority.getAuthority().split("_")[1].toString().equalsIgnoreCase("SUPERADMIN")){
                csroles.add(3);
            }
            }
        }
        return csroles;
    }

This is my managaer controller :

@RequestMapping(value="new",method=RequestMethod.POST)
    public String testMethod(@ModelAttribute("employeeDetails") EmployeeDetails details,HttpSession httpSession, Model model){
        UserDetails userDetails = getUserDetails();
        model.addAttribute("details", details);
        return "redirect:newemployee";
    }

And the for testing the manager this is what I have done:

@Test
    public void testnewEmployeePost() throws Exception{
        UserDetails userDetails = new UserDetails() {

            @Override
            public boolean isEnabled() {
                // TODO Auto-generated method stub
                return true;
            }

            @Override
            public boolean isCredentialsNonExpired() {
                // TODO Auto-generated method stub
                return true;
            }

            @Override
            public boolean isAccountNonLocked() {
                // TODO Auto-generated method stub
                return true;
            }

            @Override
            public boolean isAccountNonExpired() {
                // TODO Auto-generated method stub
                return true;
            }

            @Override
            public String getUsername() {
                // TODO Auto-generated method stub
                return "nitesh";
            }

            @Override
            public String getPassword() {
                // TODO Auto-generated method stub
                return "nitesh";
            }

            @Override
            public Collection<? extends GrantedAuthority> getAuthorities() {
                GrantedAuthority authority = new GrantedAuthority() {

                    @Override
                    public String getAuthority() {
                        // TODO Auto-generated method stub
                        return "ROLE_USER";
                    }
                };
                List<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();
                grantedAuthorities.add(authority);
                return grantedAuthorities;
            }
        };

        EmployeeDetails employeeDetails = new EmployeeDetails();
        employeeDetails.setPanCardNo("lower");
        employeeDetails.setFirstName("Nitesh");

        Mockito.when(managerController.getUserDetails()).thenReturn(userDetails);

        mockMvc.perform(post("/manager/new")
                .contentType(MediaType.ALL)
                .sessionAttr("employeeDetails", employeeDetails)
                )   
                .andExpect(model().attribute("employeeDetails", instanceOf(EmployeeDetails.class)));
    }

And the exception thrown is :

java.lang.NullPointerException
    at com.rectrix.ool.controller.DefaultController.getUserDetails(DefaultController.java:24)
    at com.rectrix.ool.test.controller.TestManagerController.testnewEmployeePost(TestManagerController.java:172)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

Kindly guide me to overcome this issue

Upvotes: 0

Views: 362

Answers (1)

shazin
shazin

Reputation: 21883

You don't need to create an annonymous UserDetails instance. You can use User which is an implementation of the UserDetails already available in Spring Security. Anyway it is not even required. And you are trying to mock the Parent Class DefaultController of the ManagerController. I have never seen or heard the ability to mock a is a relationship. What you should do is import dependency

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-test</artifactId>
    <version>4.0.4.RELEASE</version>
</dependency>

And rewrite your test as following to mock an authenticated user.

 import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;

    @Test
    public void testnewEmployeePost() throws Exception{


        EmployeeDetails employeeDetails = new EmployeeDetails();
        employeeDetails.setPanCardNo("lower");
        employeeDetails.setFirstName("Nitesh");

        mockMvc.perform(post("/manager/new")
            .with(user("nitesh")
            .password("nitesh")
            .authorities(AuthorityUtils.createAuthorityList("ROLE_USER"))
        .contentType(MediaType.ALL)
        .sessionAttr("employeeDetails", employeeDetails))   
        .andExpect(model().attribute("employeeDetails", instanceOf(EmployeeDetails.class)));
    }

Upvotes: 1

Related Questions