Jak mogę mockować zmienną pola, która jest inicjowana w tekście?
class Test {
private Person person = new Person();
...
public void testMethod() {
person.someMethod();
...
}
}
Tutaj chcę mockować person.someMethod()
podczas testowania Test.testMethod()
metody, dla której muszę mockować inicjalizację person
zmiennej. Jakaś wskazówka?
Edycja: nie mogę modyfikować klasy osoby.
java
mockito
junit4
powermockito
Bieg
źródło
źródło
Person
. Opcje obejmują dodanie konstruktora, aby to zrobić, lub dodanie metody ustawiającej.Odpowiedzi:
Mockito jest dostarczany z klasą pomocniczą, która pozwala zaoszczędzić trochę kodu płytki kotła:
import org.mockito.internal.util.reflection.Whitebox; //... @Mock private Person mockedPerson; private Test underTest; // ... @Test public void testMethod() { Whitebox.setInternalState(underTest, "person", mockedPerson); // ... }
Aktualizacja: Niestety, zespół mockito zdecydował się usunąć klasę z Mockito 2. Wracasz więc do pisania własnego standardowego kodu refleksji, użyj innej biblioteki (np. Apache Commons Lang ) lub po prostu okradnij klasę Whitebox (jest na licencji MIT ).
Aktualizacja 2: JUnit 5 zawiera własne klasy ReflectionSupport i AnnotationSupport , które mogą być przydatne i uchronić Cię przed ściąganiem kolejnej biblioteki.
źródło
internal
pakiecie i nie wydaje się już działać na Mockito 2.6.2.Dość późno na przyjęcie, ale uderzyło mnie tutaj i otrzymałem pomoc od znajomego. Nie chodziło o to, żeby użyć PowerMocka. Działa to z najnowszą wersją Mockito.
Mockito przychodzi z tym
org.mockito.internal.util.reflection.FieldSetter
.Zasadniczo pomaga modyfikować prywatne pola za pomocą odbicia.
Oto jak tego używasz:
@Mock private Person mockedPerson; private Test underTest; // ... @Test public void testMethod() { FieldSetter.setField(underTest, underTest.getClass().getDeclaredField("person"), mockedPerson); // ... verify(mockedPerson).someMethod(); }
W ten sposób możesz przekazać pozorowany obiekt, a następnie zweryfikować go później.
Oto odniesienie.
źródło
FieldSetter
nie jest już dostępne w Mockito 2.x.Class#getDeclaredField
akceptuje pojedynczy parametr, więc pareny muszą wyglądać takFieldSetter.setField(underTest, underTest.getClass().getDeclaredField("person"), mockedPerson);
. W ten sposób pomyliłem się i pomyślałem, że dobrym pomysłem może być naprawienie tego na twoim przykładzie. Dzięki za odpowiedź.Jeśli używasz Spring Test, wypróbuj org.springframework.test.util.ReflectionTestUtils
ReflectionTestUtils.setField(testObject, "person", mockedPerson);
źródło
testImplementation("org.springframework:spring-test:5.1.2.RELEASE")
Znalazłem już rozwiązanie tego problemu, o którym zapomniałem zamieścić tutaj.
@RunWith(PowerMockRunner.class) @PrepareForTest({ Test.class }) public class SampleTest { @Mock Person person; @Test public void testPrintName() throws Exception { PowerMockito.whenNew(Person.class).withNoArguments().thenReturn(person); Test test= new Test(); test.testMethod(); } }
Kluczowe punkty tego rozwiązania to:
Uruchamiam moje przypadki testowe z PowerMockRunner:
@RunWith(PowerMockRunner.class)
Poinstruuj Powermocka, aby przygotował się
Test.class
do manipulacji polami prywatnymi:@PrepareForTest({ Test.class })
I na koniec mock konstruktora dla klasy Person:
PowerMockito.mockStatic(Person.class);
PowerMockito.whenNew(Person.class).withNoArguments().thenReturn(person);
źródło
mockStatic
funkcji, ale nie jest to przedstawione w Twoim przykładzie kodu. Czy przykładowy kod powinien miećmockStatic
wywołanie, czy nie jest to wymagane dla konstruktorów?Poniższy kod może służyć do inicjalizacji programu odwzorowującego w makiecie klienta REST. To
mapper
pole jest prywatne i należy je ustawić podczas konfiguracji testu jednostkowego.import org.mockito.internal.util.reflection.FieldSetter; new FieldSetter(client, Client.class.getDeclaredField("mapper")).set(new Mapper());
źródło
Korzystając z przewodnika @ Jarda, możesz to zdefiniować, jeśli chcesz ustawić zmienną tę samą wartość dla wszystkich testów:
@Before public void setClientMapper() throws NoSuchFieldException, SecurityException{ FieldSetter.setField(client, client.getClass().getDeclaredField("mapper"), new Mapper()); }
Uważaj jednak, aby zachować ostrożność przy ustawianiu innych wartości prywatnych. Jeśli są prywatne, z jakiegoś powodu.
Na przykład używam go, na przykład, do zmiany czasu oczekiwania uśpienia w testach jednostkowych. W prawdziwych przykładach chcę spać przez 10 sekund, ale w teście jednostkowym jestem zadowolony, jeśli jest to natychmiastowe. W testach integracyjnych powinieneś przetestować rzeczywistą wartość.
źródło