Zasadniczo chcę uruchomić test na czystej karcie, więc nie chcę, aby @PostConstruct wypełnił pole danych.

Mam prywatną zmienną statyczną w klasie usług, która pobiera dane ładowane z repozytorium po pomyślnym zakończeniu kompilacji. Czy istnieje sposób na uruchomienie testów jednostkowych bez tych danych? (ze świeżymi zajęciami)

W teście mockuję funkcję getData repozytorium, ale jest tam instrukcja if empty. Ponieważ podczas kompilacji zmienna statyczna jest wypełniana, testy nie będą używać funkcji mockowanej, więc test kończy się niepowodzeniem.

To, co znalazłem, działa, to wywołanie funkcji empty variable usługi w adnotacji @Before. Ale to nie jest stabilne rozwiązanie.

Próbka kodu:

private static List<Data> data = Collections.synchronizedList(new ArrayList<Data>());

@PostConstruct
private List<Data> populateData() {

  data = repo.findData();

  return data;
}

public List<Data> getData() {

  if (data.size() == 0) {
    populateData();
  }
  return data;
}

Test:

@Mock
private Repository repo;

@Mock
private static Data data;

@InjectMocks
private Service service;

private List<Data> rows = new ArrayList<Data>();

@Before
public void mockMethodSetup() {

  //service.evictData();

  data.setValue(1);

  when(repo.findData()).thenReturn(data);

}

@Test
public void shouldReturnDataResponse() {
  List<Data> dataReturned= service.getData();
  assertEquals("Response was not equal to the mock.", dataReturned, data);
}
0
Raket Makhim 19 listopad 2019, 17:46
Repository.findData() - czy Repository jest singletonem?
 – 
Pavel Smirnov
19 listopad 2019, 17:54
Repozytorium nie jest singletonem, jest interfejsem rozszerzającym JpaRepository
 – 
Raket Makhim
19 listopad 2019, 17:57
Zmieniłem to na próbę i błąd
 – 
Raket Makhim
19 listopad 2019, 18:08

1 odpowiedź

O ile rozumiem, próbujesz zastąpić statyczne pole data czymś innym w swoim teście.

Możesz to zrobić za pomocą Reflections: link .


To może działać, ale nie musi, w zależności od tego, czy Twoje wywołanie repo.findData() działa, czy generuje wyjątek. Sugeruję, abyś nie wnosił do UnitTestu żadnego know-how dotyczącego adnotacji @PostConstruct, aby metoda nie została wykonana.


Również jeśli zdefiniujesz @Mock dla data, będziesz musiał zdefiniować dla niego zachowanie.
Pamiętaj, że data nie powinno być polem statycznym w Twoim teście.

Ps.: @InjectMocks nie ma żadnego wpływu na pola statyczne.

1
second 19 listopad 2019, 18:21
Zasadniczo chcę uruchomić test na czystej karcie, więc nie chcę @PostConstruct wypełniać pola danych. Czy zmiana, którą wprowadzają Refleksje, pozostaje w klasie usług?
 – 
Raket Makhim
19 listopad 2019, 18:24
Jakiego Runner używasz, który wywołuje @PostConstruct? Jeśli użyjesz odbić po inicjalizacji, zastąpi je, jednak jeśli zostanie utworzona inna instancja obiektu, może to zmienić ponownie.
 – 
second
19 listopad 2019, 18:26
Używam MockitoJunitRunner, który działa lokalnie, ale nie działa na CI GitLab, ponieważ musi kompilować (a więc @PostConstruct) i dlatego dane są wypełniane przed testami. Dlatego if w Service.getData() nie pozwoli mi go wypełnić.
 – 
Raket Makhim
19 listopad 2019, 18:31
MockitoJunitRunner nie ma pojęcia o @PostConstruct. Jeśli metoda jest wywoływana, musi pochodzić z innego miejsca. Sprawdź swoją konfigurację CI GitLab.
 – 
second
19 listopad 2019, 18:34
1
To przerodziło się w problem z konfiguracją. Próbując zadać inne pytanie, nie mogę odpowiedzieć na to.
 – 
second
19 listopad 2019, 18:37