Pertimbangkan tanda tangan metode seperti:
public String myFunction(String abc);
Bisakah Mockito membantu mengembalikan string yang sama dengan metode yang diterima?
Pertimbangkan tanda tangan metode seperti:
public String myFunction(String abc);
Bisakah Mockito membantu mengembalikan string yang sama dengan metode yang diterima?
Jawaban:
Anda dapat membuat Jawaban di Mockito. Mari kita asumsikan, kita memiliki antarmuka bernama Aplikasi dengan metode myFunction.
public interface Application {
public String myFunction(String abc);
}
Inilah metode pengujian dengan jawaban Mockito:
public void testMyFunction() throws Exception {
Application mock = mock(Application.class);
when(mock.myFunction(anyString())).thenAnswer(new Answer<String>() {
@Override
public String answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
return (String) args[0];
}
});
assertEquals("someString",mock.myFunction("someString"));
assertEquals("anotherString",mock.myFunction("anotherString"));
}
Karena Mockito 1.9.5 dan Java 8, Anda juga dapat menggunakan ekspresi lambda:
when(myMock.myFunction(anyString())).thenAnswer(i -> i.getArguments()[0]);
when(...).then(Return.firstParameter())
when(foo(any()).then(i -> i.getArgumentAt(0, Bar.class))
. Dan Anda bisa menggunakan referensi metode dan memanggil metode nyata.
Iterator<? extends ClassName>
yang menyebabkan semua jenis masalah dalam thenReturn()
pernyataan.
when(foo(any()).thenAnswer(i -> i.getArguments()[0])
Jika Anda memiliki Mockito 1.9.5 atau lebih tinggi, ada metode statis baru yang dapat membuat Answer
objek untuk Anda. Anda perlu menulis sesuatu seperti
import static org.mockito.Mockito.when;
import static org.mockito.AdditionalAnswers.returnsFirstArg;
when(myMock.myFunction(anyString())).then(returnsFirstArg());
atau sebagai alternatif
doAnswer(returnsFirstArg()).when(myMock).myFunction(anyString());
Perhatikan bahwa returnsFirstArg()
metode ini statis di AdditionalAnswers
kelas, yang baru untuk Mockito 1.9.5; jadi Anda akan memerlukan impor statis yang tepat.
when(...).then(returnsFirstArg())
, saya keliru when(...).thenReturn(returnsFirstArg())
yang memberijava.lang.ClassCastException: org.mockito.internal.stubbing.answers.ReturnsArgumentAt cannot be cast to
static org.mockito.AdditionalAnswers.returnsFirstArg
. ini untuk menggunakan returnsFirstArg. Juga, saya bisa melakukannya when(myMock.myFunction(any())).then(returnsFirstArg())
di Mockito 2.20. *
Dengan Java 8 dimungkinkan untuk membuat jawaban satu baris bahkan dengan versi Mockito yang lebih lama:
when(myMock.myFunction(anyString()).then(i -> i.getArgumentAt(0, String.class));
Tentu saja ini tidak berguna seperti yang AdditionalAnswers
disarankan oleh David Wallace, tetapi mungkin berguna jika Anda ingin mengubah argumen "dengan cepat".
long
, apakah ini masih bisa bekerja dengan tinju dan Long.class
?
Saya punya masalah yang sangat mirip. Tujuannya adalah untuk mengejek layanan yang tetap menggunakan Object dan dapat mengembalikannya dengan nama mereka. Layanannya terlihat seperti ini:
public class RoomService {
public Room findByName(String roomName) {...}
public void persist(Room room) {...}
}
Mock layanan menggunakan peta untuk menyimpan instance Kamar.
RoomService roomService = mock(RoomService.class);
final Map<String, Room> roomMap = new HashMap<String, Room>();
// mock for method persist
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Object[] arguments = invocation.getArguments();
if (arguments != null && arguments.length > 0 && arguments[0] != null) {
Room room = (Room) arguments[0];
roomMap.put(room.getName(), room);
}
return null;
}
}).when(roomService).persist(any(Room.class));
// mock for method findByName
when(roomService.findByName(anyString())).thenAnswer(new Answer<Room>() {
@Override
public Room answer(InvocationOnMock invocation) throws Throwable {
Object[] arguments = invocation.getArguments();
if (arguments != null && arguments.length > 0 && arguments[0] != null) {
String key = (String) arguments[0];
if (roomMap.containsKey(key)) {
return roomMap.get(key);
}
}
return null;
}
});
Kami sekarang dapat menjalankan tes kami di mock ini. Sebagai contoh:
String name = "room";
Room room = new Room(name);
roomService.persist(room);
assertThat(roomService.findByName(name), equalTo(room));
assertNull(roomService.findByName("none"));
Dengan Java 8, jawaban Steve bisa menjadi
public void testMyFunction() throws Exception {
Application mock = mock(Application.class);
when(mock.myFunction(anyString())).thenAnswer(
invocation -> {
Object[] args = invocation.getArguments();
return args[0];
});
assertEquals("someString", mock.myFunction("someString"));
assertEquals("anotherString", mock.myFunction("anotherString"));
}
SUNTING: Lebih singkat lagi:
public void testMyFunction() throws Exception {
Application mock = mock(Application.class);
when(mock.myFunction(anyString())).thenAnswer(
invocation -> invocation.getArgument(0));
assertEquals("someString", mock.myFunction("someString"));
assertEquals("anotherString", mock.myFunction("anotherString"));
}
Ini pertanyaan yang cukup lama tapi saya pikir masih relevan. Juga jawaban yang diterima hanya berfungsi untuk String. Sementara itu ada Mockito 2.1 dan beberapa impor telah berubah, jadi saya ingin membagikan jawaban saya saat ini:
import static org.mockito.AdditionalAnswers.returnsFirstArg;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
@Mock
private MyClass myClass;
// this will return anything you pass, but it's pretty unrealistic
when(myClass.myFunction(any())).then(returnsFirstArg());
// it is more "life-like" to accept only the right type
when(myClass.myFunction(any(ClassOfArgument.class))).then(returnsFirstArg());
The myClass.myFunction akan terlihat seperti:
public class MyClass {
public ClassOfArgument myFunction(ClassOfArgument argument){
return argument;
}
}
Saya menggunakan sesuatu yang serupa (pada dasarnya itu pendekatan yang sama). Kadang-kadang berguna untuk memiliki objek tiruan mengembalikan output yang telah ditentukan untuk input tertentu. Seperti ini:
private Hashtable<InputObject, OutputObject> table = new Hashtable<InputObject, OutputObject>();
table.put(input1, ouput1);
table.put(input2, ouput2);
...
when(mockObject.method(any(InputObject.class))).thenAnswer(
new Answer<OutputObject>()
{
@Override
public OutputObject answer(final InvocationOnMock invocation) throws Throwable
{
InputObject input = (InputObject) invocation.getArguments()[0];
if (table.containsKey(input))
{
return table.get(input);
}
else
{
return null; // alternatively, you could throw an exception
}
}
}
);
Anda mungkin ingin menggunakan verifikasi () dalam kombinasi dengan ArgumentCaptor untuk memastikan eksekusi dalam pengujian dan ArgumentCaptor untuk mengevaluasi argumen:
ArgumentCaptor<String> argument = ArgumentCaptor.forClass(String.class);
verify(mock).myFunction(argument.capture());
assertEquals("the expected value here", argument.getValue());
Nilai argumen jelas dapat diakses melalui argument.getValue () untuk manipulasi lebih lanjut / memeriksa / apa pun.
Ini agak lama, tetapi saya datang ke sini karena saya memiliki masalah yang sama. Saya menggunakan JUnit tetapi kali ini di aplikasi Kotlin dengan mockk. Saya memposting sampel di sini untuk referensi dan perbandingan dengan mitra Java:
@Test
fun demo() {
// mock a sample function
val aMock: (String) -> (String) = mockk()
// make it return the same as the argument on every invocation
every {
aMock.invoke(any())
} answers {
firstArg()
}
// test it
assertEquals("senko", aMock.invoke("senko"))
assertEquals("senko1", aMock.invoke("senko1"))
assertNotEquals("not a senko", aMock.invoke("senko"))
}
Anda dapat mencapai ini dengan menggunakan ArgumentCaptor
Bayangkan Anda memiliki fungsi kacang seperti itu.
public interface Application {
public String myFunction(String abc);
}
Kemudian di kelas ujian Anda:
//Use ArgumentCaptor to capture the value
ArgumentCaptor<String> param = ArgumentCaptor.forClass(String.class);
when(mock.myFunction(param.capture())).thenAnswer(new Answer<String>() {
@Override
public String answer(InvocationOnMock invocation) throws Throwable {
return param.getValue();//return the captured value.
}
});
ATAU jika Anda penggemar lambda cukup lakukan:
//Use ArgumentCaptor to capture the value
ArgumentCaptor<String> param = ArgumentCaptor.forClass(String.class);
when(mock.myFunction(param.capture()))
.thenAnswer((invocation) -> param.getValue());
Ringkasan: Gunakan argumencaptor, untuk menangkap parameter yang dilewati. Kemudian sebagai jawaban, kembalikan nilai yang ditangkap menggunakan getValue.
This doesn´t work (anymore?).
saya bekerja pada contoh saya. 2. Maaf, saya tidak jelas pada poin yang Anda coba buat. Jawabannya khusus untuk pertanyaan OP.