我想设置一个私有字段来测试一个函数

时间:2015-11-27 09:12:36

标签: java junit mockito

我有一个具有getUser函数的bean,它返回当前登录的用户,或者如果变量user为空则找到一个。

我的bean中是否有糟糕的设计,或者我应该只创建一个setUser函数?我不确定正确的方法是什么。

这是我对该AuthorizationBean的测试:

public class AuthorizationBeanTest {

    private AuthorizationBean authorizationBean;

    @Mock
    User user;

    @Mock
    UserDao userDao;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        authorizationBean = new AuthorizationBean();
        //I want to set the user to the mocked user so I can test the logout function
    }

    @Test
    public void doLogoutTest() {
        assertNotNull(authorizationBean.getUser());
        assertEquals("/login.xhtml?faces-redirect=true", authorizationBean.doLogout());
        assertNull(authorizationBean.getUser());
    }

}

以下是bean的代码:

@ManagedBean(name = "authBean")
@SessionScoped
public class AuthorizationBean implements Serializable{

    //Data access object for the users
    @Inject
    UserDao userDao;

    private User user; // The JPA entity.
    public User getUser() {
        if (user == null) {
            user = (User) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("user");
            if (user == null) {
                Principal principal = FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal();
                if (principal != null) {
                    user = userDao.findByEmail(principal.getName()); // Find User by j_username.
                }
            }
        }
        return user;
    }

    /**
     * Function that handles the logout
     * @return Redirect string that points to the login page
     */
    public String doLogout() {
        // invalidate the session, so that the session is removed
        FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
        user = null;
        // return redirect to login page
        return "/login.xhtml?faces-redirect=true";
    }


}

3 个答案:

答案 0 :(得分:1)

您可以在@Before方法中模拟用户,如下所示:

Mockito.when(authorizationBean.getUser()).thenReturn(user);

为此,您还需要模拟AuthorizationBean类。

你也可以省略MockitoAnnotations.initMocks(this);使用Mockito运行程序运行整个测试的invokation,将此注释放在测试类上:

@RunWith(MockitoJUnitRunner.class)

更新:但是,您无法测试AuthorizationBean确实嘲笑它。你的bean中有几个静态方法调用,你可以用PowerMock来模拟它们,但是使用PowerMock也是审查设计的难闻气味。

更新2 : 使用PowerMock,您实际上可以执行以下操作:

PowerMockito.mockStatic(FacesContext.class);
PowerMockito.when(FacesContext.getCurrentInstance()).thenReturn(context);

上下文是另一个模拟,然后用你的模拟用户填充会话地图。

更新3 :不要忘记运行测试用例,然后使用@RunWith(PowerMockRunner.class)。你可以查看一个更详细的例子here,但如果将来链接被破坏,上面的说明应该已经给你一个良好的开端。

答案 1 :(得分:1)

我通常做的是,为了简单起见,我将字段包设为私有,并使用guava's @VisibleForTesting

对其进行注释
@VisibleForTesting User user; // The JPA entity.

答案 2 :(得分:1)

您可以使用好的(或不喜欢的)旧java.reflection包来设置私有字段。

Field userField = authorizationBean.getClass().getDeclaredField("user");
userField.setAccessible(true);
userField.set(authorizationBean, someUser);

在测试范围内,我认为它并不像它看起来那么糟糕......