【问题标题】:Spring MVC test controller with spring security具有弹簧安全性的 Spring MVC 测试控制器
【发布时间】:2016-11-25 18:43:24
【问题描述】:

我正在尝试为测试控制器编写测试用例,这是控制器的代码

@Controller
@RequestMapping("/")
@SessionAttributes({"roles", "departments"})
public class AppController {

    @Autowired
    UserService userService;

    @Autowired
    RoleService roleService;

    @Autowired
    DepartmentService departmentService;

    @Autowired
    MessageSource messageSource;

    @Autowired
    PersistentTokenBasedRememberMeServices persistentTokenBasedRememberMeServices;

    @Autowired
    AuthenticationTrustResolver authenticationTrustResolver;

    static final Logger logger = LoggerFactory.getLogger(AppController.class);

    /**
     * This method will list all existing users.
     */
    @RequestMapping(value = { "/", "/list" }, method = RequestMethod.GET)
    public String listUsers(ModelMap model) {

        List<User> users = userService.findAllUsers();
        model.addAttribute("users", users);
        model.addAttribute("loggedinuser", getPrincipal());
        return "userslist";
    }
    /**
     * This method returns the principal[user-name] of logged-in user.
     */
    private String getPrincipal(){
        String userName = null;
        Object principal = getCurrentUser();

        if (principal instanceof UserDetails) {
            userName = ((UserDetails)principal).getUsername();
        } else {
            userName = principal.toString();
        }
        return userName;
    }

    private Object getCurrentUser(){
        return SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    }
//The rest part of the controller}

我根据本教程使用 TestNG:http://websystique.com/springmvc/spring-4-mvc-and-hibernate4-integration-testing-example-using-annotations/,目前我的测试用例中有以下内容:

//all the import file
public class AppControllerTest {

    @Mock
    UserService userService;

    @Mock
    MessageSource message;

    @InjectMocks
    AppController appController;

    @Spy
    List<User> users = new ArrayList<User>();

    @Spy
    ModelMap model;

    @Mock
    BindingResult result;

    @BeforeClass
    public void setUp(){
        MockitoAnnotations.initMocks(this);
        users = getUsers();
    }

    private List<User> getUsers() {
        // TODO Auto-generated method stub
        User u1 = new User();
        u1.setId(1);
        u1.setFirstName("Admin");
        u1.setLastName("Admin");
        u1.setUsername("admin");
        u1.setEmail("admin@akb.co.jp");
        u1.setDateOfBirth(new LocalDate());
        u1.setPassword("admin");
        Department admin = new Department();
        admin.setId(1);
        admin.setName("Admin");
        admin.setDescription("Admin");
        u1.setDepartment(admin);
        Role adminRole = new Role();
        adminRole.setId(1);
        adminRole.setRoleName("ADMIN");
        Set<Role> roles = new HashSet<>();
        roles.add(adminRole);
        u1.setRoles(roles);

        User u2 = new User();
        u2.setId(1);
        u2.setFirstName("Alice");
        u2.setLastName("Lin");
        u2.setUsername("alice.lin");
        u2.setEmail("alice.lin@akb.co.jp");
        u2.setDateOfBirth(new LocalDate());
        u2.setPassword("Alice0102");
        u2.setDepartment(admin);
        u2.setRoles(roles);

        users.add(u1);
        users.add(u2);
        return users;
    }

    @Test
    public void listUsers(){
        when(userService.findAllUsers()).thenReturn(users);
        Assert.assertEquals(appController.listUsers(model), "userslist");
        Assert.assertEquals(model.get("users"), users);
        verify(userService, atLeastOnce()).findAllUsers();
    }
}

现在的问题是,如果我没有评论这一行 model.addAttribute("loggedinuser", getPrincipal()); 在我的控制器类中,当我运行 maven 测试时,它会抛出空指针异常,这很明显,因为在我的测试用例中我没有登录到应用程序。我该怎么做才能使通过的测试包含此行?

【问题讨论】:

    标签: java spring maven spring-mvc spring-security


    【解决方案1】:

    您应该重构您的代码,以便 getCurrentUser() 调用存在于一个单独的类中。无论如何,您应该将它们分开,因为很可能其他控制器需要进行相同的调用。但是对于这种情况,您需要重构,因为您无法模拟私有方法调用(至少不使用 Mockito)。

    一旦与用户相关的调用位于单独的类中,您就可以像执行上述其他服务一样使用@Mock 注解对其进行模拟。

    【讨论】:

    • 可以,但是还有一个问题,在实际应用中,listUsers()会在用户登录系统后调用,例如用户名是“admin”,因此会设置“loggedinuser”到“管理员”。我有什么办法可以在测试中解决这个问题吗?喜欢Assert.assertEquals(model.get("loggedinuser"), "admin");会通过吗?
    • 尝试类似:when(loggedInService.getPrincipal()).thenReturn("admin");
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-28
    • 2019-02-03
    • 1970-01-01
    • 2015-09-23
    • 2019-10-07
    • 2015-03-07
    • 1970-01-01
    相关资源
    最近更新 更多