使用StringBuilder作为参数失败时的Java Mockito。

Pra*_*ara 3 java mockito

下面oneLoginAuthUtil是模拟的JUnit测试。但是Mockito.when正在返回nulloneLoginAuthUtil.getMetaData一直都是null。下面是代码-

public void func() throws Exception {
    StringBuilder b = new StringBuilder("test");
    RequestContext context = new RequestContext();
    Mockito.when(oneLoginAuthUtil.getMetaData(context, b)).thenReturn("abcdef");
    ResponseEntity<Object> response = loginControllerImpl.handleGetMetaDataEndPointImpl(context);
}

public String getMetaData(RequestContext context, StringBuilder b) throws Exception {
    Auth auth = getOneLoginAuthObject(context);
    final Saml2Settings settings = auth.getSettings();
    String metadata = settings.getSPMetadata();
    List<String> errors = Saml2Settings.validateMetadata(metadata);
    if (!errors.isEmpty()) {
        b.append(errors.toString());
        throw new SSOException("metadata_validation_error");
    }
    return metadata;
}

public ResponseEntity<Object> handleGetMetaDataEndPointImpl(RequestContext context) {
    try {
        StringBuilder b = new StringBuilder();
        String metadata = oneLoginAuthUtil.getMetaData(context, b);
        log.info(metadata);
        return new ResponseEntity<>(metadata, new HttpHeaders(), HttpStatus.CREATED);
    } catch (Exception e) {
        return new ResponseEntity<>("<error>Exception: " + e.getMessage() + "</error>", new HttpHeaders(),
                HttpStatus.CREATED);
    }
}
Run Code Online (Sandbox Code Playgroud)

但是oneLoginAuthUtil.getMetaData没有StringBuilderas参数的方法效果很好。

Nic*_*tto 5

null之所以返回,是因为当您模拟使用特定实例作为参数的方法时,当且仅当测试过程中提供的参数等于您在模拟过程中提供的参数时(明显不是这种情况),Mockito才会返回映射的返回值。Mockito没有匹配项,因此它返回方法的默认值,该方法返回在名为的模拟对象上调用的对象null

换句话说Mockito.when(oneLoginAuthUtil.getMetaData(context, b)),等价于Mockito.when(oneLoginAuthUtil.getMetaData(Mockito.eq(context), Mockito.eq(b))),因为类StringBuilder不覆盖方法equals(Object obj),模拟时提供的实例不等于测试时提供的实例,因为它们不是相同的实例(唯一的可能是依赖于的默认实现equals(Object obj)),以便您获得此行为。

因此,您应该使用Mockito.any(StringBuilder.class)与任何类型StringBuilder的实例进行匹配,以使实例不再需要相等,然后您的代码将是:

Mockito.when(
    oneLoginAuthUtil.getMetaData(Mockito.eq(context), Mockito.any(StringBuilder.class))
).thenReturn("abcdef");
Run Code Online (Sandbox Code Playgroud)

假设您的主类是LoginControllerImpl并且它具有oneLoginAuthUtiltype 的member字段OneLoginAuthUtil,则可以使用批注@InjectMocks直接注入您的type的模拟,OneLoginAuthUtil然后完整的代码应为:

@RunWith(MockitoJUnitRunner.class)
public class LoginControllerImplTest {

    @Mock
    private OneLoginAuthUtil oneLoginAuthUtil;
    @InjectMocks
    private LoginControllerImpl loginControllerImpl;

    @Test
    public void func() throws Exception {
        RequestContext context = new RequestContext();
        Mockito.when(
            oneLoginAuthUtil.getMetaData(
                Mockito.eq(context), Mockito.any(StringBuilder.class)
            )
        ).thenReturn("abcdef");

        ResponseEntity<Object> response 
            = loginControllerImpl.handleGetMetaDataEndPointImpl(context);
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)