如何使用 Mockito 模拟 Restriction.eq( )

Lot*_*ava 5 java unit-testing hibernate mockito powermock

I\xc2\xb4m 在使用 Mockito 创建测试时遇到一些麻烦。在使用 Eclipse 进行调试期间,我得到了一个nullfrom Restrictions.eq,我完成了创建静态模拟的每一步Restrictions

\n\n
@RunWith(PowerMockRunner.class)\n@PrepareForTest({ RequisicaoList.class, StatusMessages.class,\n    FacesMessages.class, Restrictions.class })\npublic class RequisicaoListTest {\n\n...\n\n@SuppressWarnings("unchecked")\npublic String criteriaContigencia() {\n    Criteria criteria = criarCriteria(Requisicao.class);\n\n    criteria.createAlias("produto", "prod");        \n    criteria.add(Restrictions.eq("prod.ar",arSelecionada));\n\n    if (getExemplo().getNrProtocolo() != null)\n        criteria.add(Restrictions.eq("nrProtocolo", getExemplo()\n                .getNrProtocolo()));\n\n    situacoesPesquisa.clear();\n    situacoesPesquisa.add(SituacaoRequisicao.PENDENTE_PAGAMENTO);\n    situacoesPesquisa.add(SituacaoRequisicao.PENDENTE_AGENDAMENTO);\n    if (!situacoesPesquisa.isEmpty()) {\n        criteria.add(Restrictions.in("situacao", situacoesPesquisa));\n    }   \n\n    if (getExemplo().getResponsavel() != null && StringUtils.isNotBlank(getExemplo().getResponsavel().getCpf())) {\n            criteria = criteria.createCriteria("responsavel");\n            criteria = criteria.add(Restrictions.eq("cpf", getExemplo().getResponsavel().getCpf()));\n    }\n\n    resultado = Collections.checkedList(criteria.list(),Requisicao.class);\n\n    return null;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我的代码将 ManagedBean 与持久层混合,我可以\xc2\xb4t 更改它,但我必须为该项目创建测试。

\n\n

这里的问题是模拟

\n\n
Restrictions.eq("cpf", getExemplo().getResponsavel().getCpf())\n
Run Code Online (Sandbox Code Playgroud)\n\n

因为即使我也这样做:

\n\n
SimpleExpression simpleExpressionEq = mock(SimpleExpression.class);\nPowerMockito.mockStatic(Restrictions.class);\nwhen(Restrictions.eq("cpf", "00000000091")).thenReturn(simpleExpressionEq);\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后我仍然得到null返回Restriction.eq,甚至传递了观察值。但在调试过程中,如果我在表达式视图中创建表达式:

\n\n
Restrictions.eq("cpf", "00000000091"))\n
Run Code Online (Sandbox Code Playgroud)\n\n

它工作正常并返回一个嘲笑的SimpleExpression

\n

jhe*_*cks 1

如果

Restrictions.eq("cpf", "00000000091"))
Run Code Online (Sandbox Code Playgroud)

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

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

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

verify(mockCriteria).add(argThat(toStringEq(Restrictions.eq("cpf", "0000000091"))));
Run Code Online (Sandbox Code Playgroud)

这是简单的匹配器类:

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);
    }

}
Run Code Online (Sandbox Code Playgroud)