Mockowanie zmiennych wewnątrz metody testowanej.

0

Cześć, jak przetestować poniższy kod?

@Service
public class Premia {
    public double oblicz(double baza) {
        double retn = 0d;
        ZonedDateTime zdt = ZonedDateTime.now();
        if (zdt.getMonth() == Month.FEBRUARY) {
            retn = 3d;
        } else {
            retn = 1.1d;
        }
        return retn * baza;
    }
}

Założenia: Nie można modyfikować kodu oraz pomijamy, że został użyty typ double.

Próbowałem z PowerMock oraz szukałem rozwiązań, ale nic mogę nic znaleźć :(

Test, który próbowałem skleić ....

@SpringBootTest()
@PrepareForTest({ZonedDateTime.class})
class Demo2ApplicationTests {

	@Autowired
	Premia premia;
	@Test
	void mocking() throws Exception {
		PowerMockito.mockStatic(ZonedDateTime.class);
		ZonedDateTime zdt  = ZonedDateTime.of(2020,2,2,2,2,2,2,ZoneId.of("+1"));
		PowerMockito.when(ZonedDateTime.now()).thenReturn(zdt);
		Assertions.assertThat(premia.oblicz(1200)).isEqualTo(3600);
	}

}

W jaki sposób mokujecie wewnętrzne zmienne?
Z góry dzięki za pomoc

2

Mockowanie statickow to sredni pomysl.
Jakis czas temu grozilo to wyciekami pamieci.
Widziales to?
https://www.codeproject.com/Articles/806508/Using-PowerMockito-to-Mock-Final-and-Static-Method

1

@vpiotr: Dziękuję za artykuł zaraz się z nim zapoznam.

Dostałem podobne zadanie na jednej z rozmów rekrutacyjnych. Klasę Premia mam traktrować jako legacy code i muszę przetestować ten przypadek.

18

jak przetestować February? To proste :

LocalDateTime now = LocalDateTime.now();
LocalDateTime nextFebruary = now.withMonth(2).plusYears(1);
long waitTime = ChronoUnit.MILLIS.between(now, nextFebruary);
try { Thread.sleep(waitTime ); } catch (InterruptedException nieBoNie) {}
double wynik = premia.oblicz(4.1d);
.... //asercje

dla innego miesiąca dajesz co innego w withMonth - wybierz najlepiej styczeń (==1), to będziesz krócej czekał.

1

@impimp94: Nie potrzeba tam czasem ustawić jakieś @RunWith(PowerMockRunner.class)? Inaczej te PrepareForTest i mockStatic nie będą działać.

0

Ciekawy wpis o tym można znaleźć tutaj - https://www.baeldung.com/java-override-system-time . Do podobnego casu autor zaproponował rozwiązanie korzystające z AOP co jest całkiem pomysłowym rozwiązaniem.

3

Bez sensu. Trzeba ten kod zrefaktorować tak, żeby był testowalny. Jeśli to zadanie rekrutacyjne, to tym bardziej - nikt o zdrowych zmysłach przecież nie będzie sprawdzał czy umiesz w antypatterny :)

1

Może chodziło o przetestowanie jak silną psychikę ma rekrutowany?
a) czy zawiesi się jak Sheldon
b) czy zawinie 💩 w sreberko używając PowerMockito
c) czy zna styl Rajesha (patrz post @jarekr000000)
d) czy się uprze że trzeba to zrefaktorować?
e) czy wyjdzie ze spotkania jeśli się nie da?

1 użytkowników online, w tym zalogowanych: 0, gości: 1