4

我在使用 Mockito 创建测试时遇到了一些麻烦。在使用 Eclipse 进行调试期间,我得到了一个null来自Restrictions.eq,我做了每一步来创建一个静态模拟Restrictions

@RunWith(PowerMockRunner.class)
@PrepareForTest({ RequisicaoList.class, StatusMessages.class,
    FacesMessages.class, Restrictions.class })
public class RequisicaoListTest {

...

@SuppressWarnings("unchecked")
public String criteriaContigencia() {
    Criteria criteria = criarCriteria(Requisicao.class);

    criteria.createAlias("produto", "prod");        
    criteria.add(Restrictions.eq("prod.ar",arSelecionada));

    if (getExemplo().getNrProtocolo() != null)
        criteria.add(Restrictions.eq("nrProtocolo", getExemplo()
                .getNrProtocolo()));

    situacoesPesquisa.clear();
    situacoesPesquisa.add(SituacaoRequisicao.PENDENTE_PAGAMENTO);
    situacoesPesquisa.add(SituacaoRequisicao.PENDENTE_AGENDAMENTO);
    if (!situacoesPesquisa.isEmpty()) {
        criteria.add(Restrictions.in("situacao", situacoesPesquisa));
    }   

    if (getExemplo().getResponsavel() != null && StringUtils.isNotBlank(getExemplo().getResponsavel().getCpf())) {
            criteria = criteria.createCriteria("responsavel");
            criteria = criteria.add(Restrictions.eq("cpf", getExemplo().getResponsavel().getCpf()));
    }

    resultado = Collections.checkedList(criteria.list(),Requisicao.class);

    return null;
}

我的代码将 managedBean 与持久层混合在一起,我无法更改,但我必须为该项目创建测试。

这里的问题是模拟

Restrictions.eq("cpf", getExemplo().getResponsavel().getCpf())

因为即使我这样做:

SimpleExpression simpleExpressionEq = mock(SimpleExpression.class);
PowerMockito.mockStatic(Restrictions.class);
when(Restrictions.eq("cpf", "00000000091")).thenReturn(simpleExpressionEq);

然后我仍然null从 获得回报Restriction.eq,甚至传递了规范值。但是在调试过程中,如果我在表达式视图中做一个表达式:

Restrictions.eq("cpf", "00000000091"))

它工作正常并返回一个模拟SimpleExpression

4

2 回答 2

2

我认为Restrictions在您测试此方法时进行模拟是没有意义的。此方法的目的是包装数据访问(Hibernate 和您正在使用的任何数据库)。因此,此方法的一个有用测试将是确保您正确使用数据库的测试。

因此,我建议不要编写一个模拟所有内容的单元测试,而是编写一个集成测试。使用内存数据库,例如 H2 (http://h2database.com);并编写一个设置适当数据的测试,然后实际选择它。然后,您对该方法实际上在做它应该做的事情的信心程度将远远超过单元测试给您的信心。

于 2012-03-21T06:31:30.290 回答
1

如果

Restrictions.eq("cpf", "00000000091"))

正确返回,那么问题可能出在getExemplo().getResponsavel().getCpf(). 你确定它返回“00000000091”吗?您没有包含足够的代码来判断这是否是问题所在,但值得调查。

另一种方法是完全避免嘲笑Restrictions。当我想做这样的事情时,我使用真正的 Restrictions 类并让它返回一个真正的 Criterion。我编写了一个简单的“toStringEq”匹配器,可以用来模拟或验证 Criteria 对象的行为。当然,对象的 toString() 值的匹配与实际相等的匹配是不一样的,但是由于 Criterion 对象使用实例相等来进行相等,但是对于具有相同 toString() 值的 Criterion 对象在功能上是等效的,我'我发现它对于这个用例非常方便。

例如,在您调用之后,如果您有一个模拟 Criteria 对象,您可以拥有:

verify(mockCriteria).add(argThat(toStringEq(Restrictions.eq("cpf", "0000000091"))));

这是简单的匹配器类:

import org.hamcrest.Description;
import org.mockito.ArgumentMatcher;

public class HamcrestToStringMatcher<T> extends ArgumentMatcher<T> {

    private T toMatch;

    public HamcrestToStringMatcher(T toMatch) {
        this.toMatch = toMatch;
    }

    @Override
    public void describeTo(Description description) {
        description.appendText(toMatch == null ? "null" : toMatch.toString());
    }

    @Override
    public boolean matches(Object argument) {
        return ((toMatch == null && argument == null) || (toMatch != null
                && argument != null && toMatch.toString().equals(
                argument.toString())));
    }

    public static <T> HamcrestToStringMatcher<T> toStringEq(T toMatch) {
        return new HamcrestToStringMatcher<T>(toMatch);
    }

}
于 2012-03-20T19:48:40.497 回答