سؤال

أنا أختبر فصلًا معينًا. يتم إنشاء هذا الفصل داخليًا كائن "getMethod" الذي يتم تمريره إلى كائن "httpclient" الذي يتم حقنه في الفئة التي تم اختبارها.

أنا أسخر من فئة "httpclient" ، لكنني سأحتاج إلى تعديل سلوك فئة "getMethod" أيضًا. ألعب مع PresumentCaptor ، لكن لا يبدو أنني قادر على الحصول على كائن تم إنشاءه في مكالمة "متى".

مثال:

HttpClient mockHttpClient = mock(HttpClient.class);
ArgumentCaptor<GetMethod> getMethod = ArgumentCaptor.forClass(GetMethod.class);
when(mockHttpClient.executeMethod(getMethod.capture())).thenReturn(HttpStatus.SC_OK);
when(getMethod.getValue().getResponseBodyAsStream()).thenReturn(new FileInputStream(source));

إجابة:

org.mockito.exceptions.base.MockitoException: 
No argument value was captured!
You might have forgotten to use argument.capture() in verify()...
...or you used capture() in stubbing but stubbed method was not called.
Be aware that it is recommended to use capture() only with verify()
هل كانت مفيدة؟

المحلول 2

حسنًا ، هذه هي الطريقة التي حللت بها. قليلا معقدة ولكن لم يتمكن من العثور على أي طريقة أخرى.

في فئة الاختبار:

private GetMethod getMethod;

public void testMethod() {
    when(mockHttpClient.executeMethod(any(GetMethod.class))).thenAnswer(new ExecuteMethodAnswer());
    //Execute your tested method here.
    //Acces the getMethod here, assert stuff against it.  
}

private void setResponseStream(HttpMethodBase httpMethod, InputStream inputStream) throws NoSuchFieldException, IllegalAccessException {
    Field privateResponseStream = HttpMethodBase.class.getDeclaredField("responseStream");
    privateResponseStream.setAccessible(true);
    privateResponseStream.set(httpMethod, inputStream);
}

private class ExecuteMethodAnswer implements Answer {
    public Object answer(InvocationOnMock invocation) throws FileNotFoundException,
                                                             NoSuchFieldException, IllegalAccessException {
        getMethod = (GetMethod) invocation.getArguments()[0];
        setResponseStream(getMethod, new FileInputStream(source));
        return HttpStatus.SC_OK;
    }
}

نصائح أخرى

لا يمكنك الاستخدام when على getMethod ، لأن getMethod ليس وهمية. لا يزال كائنًا حقيقيًا تم إنشاؤه بواسطة فصلك.

PresumentCaptor لديه غرض مختلف تماما. الشيك القسم 15 هنا.

يمكنك جعل الكود الخاص بك أكثر قابلية للاختبار. بشكل عام ، يصعب اختبار الفصول التي تخلق حالات جديدة من الفصول الأخرى. ضع بعض المصنع في هذا الفصل لإنشاء طرق GET/POST ، ثم في اختبار يسخر من هذا المصنع ، وجعله أساليب GET/POST.

public class YourClass {
  MethodFactory mf;

  public YourClass(MethodFactory mf) {
    this.mf = mf;
  }

  public void handleHttpClient(HttpClient httpClient) {
    httpClient.executeMethod(mf.createMethod());
    //your code here
  }
}

ثم في الاختبار يمكنك القيام به:

HttpClient mockHttpClient = mock(HttpClient.class);
when(mockHttpClient.executeMethod(any(GetMethod.class)).thenReturn(HttpStatus.SC_OK);

MethodFactory factory = mock(MethodFactory.class);
GetMethod get = mock(GetMethod.class);
when(factory.createMethod()).thenReturn(get);
when(get.getResponseBodyAsStream()).thenReturn(new FileInputStream(source));

تحديث

يمكنك أيضًا تجربة بعض الاختراق السيئ ، و Answer والوصول إلى الأجزاء الخاصة لـ GetMethod ؛) عن طريق التفكير. (هذا حقًا اختراق سيء)

when(mockHttpClient.executeMethod(any(GetMethod.class))).thenAnswer(new Answer() {
  Object answer(InvocationOnMock invocation) {
    GetMethod getMethod = (GetMethod) invocation.getArguments()[0];

    Field respStream = HttpMethodBase.class.getDeclaredField("responseStream");
    respStream.setAccessible(true);
    respStream.set(getMethod, new FileInputStream(source));

    return HttpStatus.SC_OK;
  }
});
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top