ทุกคนช่วยยกตัวอย่างให้ฉันดูวิธีใช้org.mockito.ArgumentCaptor
คลาสได้อย่างไรและมันแตกต่างจากแมทช์ง่ายๆที่มาพร้อมกับ mockito
ฉันอ่านเอกสาร mockito ที่ให้มา แต่เอกสารเหล่านั้นไม่ได้อธิบายอย่างชัดเจนไม่มีผู้ใดสามารถอธิบายได้อย่างชัดเจน
ทุกคนช่วยยกตัวอย่างให้ฉันดูวิธีใช้org.mockito.ArgumentCaptor
คลาสได้อย่างไรและมันแตกต่างจากแมทช์ง่ายๆที่มาพร้อมกับ mockito
ฉันอ่านเอกสาร mockito ที่ให้มา แต่เอกสารเหล่านั้นไม่ได้อธิบายอย่างชัดเจนไม่มีผู้ใดสามารถอธิบายได้อย่างชัดเจน
คำตอบ:
ฉันเห็นด้วยกับสิ่งที่ @fge พูดมากกว่านั้น ให้ดูตัวอย่าง พิจารณาว่าคุณมีวิธี:
class A {
public void foo(OtherClass other) {
SomeData data = new SomeData("Some inner data");
other.doSomething(data);
}
}
ตอนนี้ถ้าคุณต้องการตรวจสอบข้อมูลภายในคุณสามารถใช้ captor:
// Create a mock of the OtherClass
OtherClass other = mock(OtherClass.class);
// Run the foo method with the mock
new A().foo(other);
// Capture the argument of the doSomething function
ArgumentCaptor<SomeData> captor = ArgumentCaptor.forClass(SomeData.class);
verify(other, times(1)).doSomething(captor.capture());
// Assert the argument
SomeData actual = captor.getValue();
assertEquals("Some inner data", actual.innerData);
OtherClass
เป็นจำลองและตามที่กำหนดไว้ในขณะนี้doSomething()
จะไม่จริงทำอะไรมันเพียงบันทึกวัตถุที่ผ่าน ซึ่งหมายความว่าจะถูกจับตามสภาพเดิมก่อนที่จะdoSomething
ถูกดำเนินการ
verify
, times(1)
เป็นค่าเริ่มต้นและสามารถละเว้น
verify
เมธอดมันจะใช้ข้อมูลนั้นเพื่อทำการจับคู่กับการตรวจสอบที่คุณทำ สำหรับทุกพารามิเตอร์มันถามว่ามันตรงกับสายเฉพาะมันตรวจสอบ เมื่อมีการตรวจสอบ ArgumentCaptor มันก็จะเก็บค่าที่มันถูกเรียกด้วยดังนั้นเมื่อverify
สิ้นสุดมันจะเก็บการร้องขอที่เกี่ยวข้องทั้งหมด มันเป็นวิธีการทำงานคร่าวๆ หวังว่ามันจะช่วย
ความแตกต่างที่สำคัญสองประการคือ:
ArgumentCaptor
สามารถจับภาพมากขึ้นมากกว่าหนึ่งครั้งหากต้องการแสดงตัวอย่างหลังให้พูดว่าคุณมี:
final ArgumentCaptor<Foo> captor = ArgumentCaptor.forClass(Foo.class);
verify(x, times(4)).someMethod(captor.capture()); // for instance
จากนั้นผู้จับกุมจะสามารถให้คุณเข้าถึงข้อโต้แย้งทั้ง 4 ข้อซึ่งคุณสามารถทำการยืนยันแยกต่างหากได้
ความจริงข้อนี้หรือข้อโต้แย้งใด ๆ เนื่องจาก a VerificationMode
ไม่ได้ จำกัด อยู่ที่การร้องขอจำนวนคงที่ ไม่ว่าในกรณีใดผู้จับกุมจะให้สิทธิ์การเข้าถึงแก่คุณหากคุณต้องการ
นี่ยังมีประโยชน์ที่การทดสอบดังกล่าวนั้นง่ายกว่าการเขียนของคุณเองArgumentMatcher
โดยเฉพาะอย่างยิ่งถ้าคุณรวม mockito กับ assertj
โอ้และโปรดพิจารณาใช้ TestNG แทน JUnit
ขั้นตอนในการตรวจสอบเต็มรูปแบบคือ:
เตรียมแคปเตอร์:
ArgumentCaptor<SomeArgumentClass> someArgumentCaptor = ArgumentCaptor.forClass(SomeArgumentClass.class);
ตรวจสอบการเรียกขึ้นอยู่กับองค์ประกอบ (ผู้ทำงานร่วมกันของเรื่องภายใต้การทดสอบ) ครั้ง (1) เป็นค่าเริ่มต้นดังนั้นจึงจำเป็นต้องเพิ่ม
verify(dependentOnComponent, times(1)).send(someArgumentCaptor.capture());
รับอาร์กิวเมนต์ที่ส่งผ่านไปยังผู้ทำงานร่วมกัน
SomeArgumentClass someArgument = messageCaptor.getValue();
someArgument สามารถใช้สำหรับการยืนยัน
ที่นี่ฉันจะให้คุณตัวอย่างที่ถูกต้องของวิธีการโทรกลับหนึ่ง ดังนั้นเราจึงมีวิธีเช่นวิธีการเข้าสู่ระบบ ():
public void login() {
loginService = new LoginService();
loginService.login(loginProvider, new LoginListener() {
@Override
public void onLoginSuccess() {
loginService.getresult(true);
}
@Override
public void onLoginFaliure() {
loginService.getresult(false);
}
});
System.out.print("@@##### get called");
}
ฉันยังใส่คลาสผู้ช่วยทั้งหมดที่นี่เพื่อทำให้ตัวอย่างชัดเจนยิ่งขึ้น: คลาส loginService
public class LoginService implements Login.getresult{
public void login(LoginProvider loginProvider,LoginListener callback){
String username = loginProvider.getUsername();
String pwd = loginProvider.getPassword();
if(username != null && pwd != null){
callback.onLoginSuccess();
}else{
callback.onLoginFaliure();
}
}
@Override
public void getresult(boolean value) {
System.out.print("login success"+value);
}}
และเรามีผู้ฟัง LoginListener เป็น:
interface LoginListener {
void onLoginSuccess();
void onLoginFaliure();
}
ตอนนี้ฉันแค่ต้องการทดสอบวิธีการเข้าสู่ระบบ () ของการเข้าชั้นเรียน
@Test
public void loginTest() throws Exception {
LoginService service = mock(LoginService.class);
LoginProvider provider = mock(LoginProvider.class);
whenNew(LoginProvider.class).withNoArguments().thenReturn(provider);
whenNew(LoginService.class).withNoArguments().thenReturn(service);
when(provider.getPassword()).thenReturn("pwd");
when(provider.getUsername()).thenReturn("username");
login.getLoginDetail("username","password");
verify(provider).setPassword("password");
verify(provider).setUsername("username");
verify(service).login(eq(provider),captor.capture());
LoginListener listener = captor.getValue();
listener.onLoginSuccess();
verify(service).getresult(true);
อย่าลืมเพิ่มคำอธิบายประกอบด้านบนคลาสการทดสอบด้วย
@RunWith(PowerMockRunner.class)
@PrepareForTest(Login.class)
captor
ที่กำหนดไว้ในคำตอบของคุณ?
doSomething(data)
กลายพันธุ์innerData
การเปลี่ยนแปลงนั้นจะเกิดassertEquals("Some inner data", actual.innerData)
ขึ้นหรือจะinnerData
ถูกจับเหมือนเดิมก่อนที่จะdoSomething
ถูกประหารชีวิต?