Close Menu
    Ciekawe

    Jak podłączyć telefon do monitora? Przewodowe i bezprzewodowe sposoby

    2025-12-08

    Co można wrzucić w koszty firmy jednoosobowej? Lista i praktyczne przykłady

    2025-12-03

    Jak podłączyć okulary VR do PS4? Poradnik podłączenia i konfiguracji

    2025-12-02
    Facebook X (Twitter) Instagram
    CPP Polska
    Facebook X (Twitter) Instagram
    • Biznes

      Co można wrzucić w koszty firmy jednoosobowej? Lista i praktyczne przykłady

      2025-12-03

      Jak zapobiec wyciekom danych firmowych?

      2025-11-28

      Ile kosztuje prowadzenie jednoosobowej działalności gospodarczej? Przegląd opłat

      2025-11-10

      Jak wziąć samochód w leasing bez firmy? Poradnik dla osób fizycznych

      2025-10-29

      Jak założyć firmę jednoosobową krok po kroku – koszty, formalności i czas trwania

      2025-10-23
    • Technologie

      Jak podłączyć telefon do monitora? Przewodowe i bezprzewodowe sposoby

      2025-12-08

      Jak podłączyć okulary VR do PS4? Poradnik podłączenia i konfiguracji

      2025-12-02

      Jak zapobiec wyciekom danych firmowych?

      2025-11-28

      Jak sprawdzić rozdzielczość monitora w Windows i macOS?

      2025-11-26

      Jak zresetować laptopa Acer do ustawień fabrycznych? Poradnik krok po kroku

      2025-11-25
    • Programowanie

      Maszyna stanów oparta o std::variant

      2025-10-07

      Tablice w C++ od podstaw – deklaracja, inicjalizacja, iteracja i typowe pułapki

      2025-10-07

      std::deque w C++ – kiedy wybrać dwukierunkową kolejkę zamiast vectora

      2025-10-07

      itoa i std::to_chars – konwersja liczb na tekst bez narzutu wydajności

      2025-10-07

      strcpy vs strncpy vs std::string – bezpieczne kopiowanie łańcuchów w C++

      2025-10-07
    • Inne

      Jak prowadzić blog programistyczny i dzielić się wiedzą?

      2025-06-28
    CPP Polska
    Home»C++»Google Mock – definiowanie zachowań i oczekiwań
    C++

    Google Mock – definiowanie zachowań i oczekiwań

    Oskar KlimkiewiczBy Oskar KlimkiewiczUpdated:2025-06-28Brak komentarzy4 Mins Read
    Share Facebook Twitter LinkedIn Email Copy Link
    Follow Us
    RSS
    a computer screen with a lot of text on it
    Share
    Facebook Twitter LinkedIn Email Copy Link

    Google Mock – definiowanie zachowań i oczekiwań w testach jednostkowych

    Framework Google Mock (GMock) stanowi kluczowy komponent ekosystemu GoogleTest dla języka C++, umożliwiający tworzenie dynamicznych atrap (mock objects) w testach jednostkowych. Atrapy implementują interfejsy rzeczywistych obiektów, pozwalając na precyzyjne sterowanie zachowaniami oraz walidację interakcji. Niniejszy artykuł omawia koncepcję deklarowania zachowań za pomocą ON_CALL oraz definiowania oczekiwań poprzez EXPECT_CALL, wraz z praktycznymi zastosowaniami i potencjalnymi pułapkami.

    Deklarowanie klas atrap

    Podstawą pracy z GMock jest definicja klasy atrapy z wykorzystaniem makra MOCK_METHOD. Składnia wymaga określenia:

    1. Typu zwracanego,
    2. nazwy metody,
    3. listy argumentów (w nawiasach),
    4. opcjonalnych kwalifikatorów (np. const, override, noexcept).
      Przykład deklaracji atrapy dla interfejsu Turtle:
    class MockTurtle : public Turtle {
    public:
    MOCK_METHOD(void, PenUp, (), (override));
    MOCK_METHOD(void, PenDown, (), (override));
    MOCK_METHOD(void, Forward, (int distance), (override));
    };
    

    Kwalifikator override jest zalecany przy nadpisywaniu metod wirtualnych, zaś const jest obowiązkowy dla metod zadeklarowanych jako stałe. Ewolucja składni pozwala również na obsługę referencji (ref(&)/ref(&&)) oraz specyfikatorów wyjątków.

    Definiowanie zachowań z ON_CALL

    Makro ON_CALL służy do deklarowania domyślnych zachowań atrapy, niezależnych od ścisłych oczekiwań testowych. Składnia:

    ON_CALL(mock_object, method_name(matchers))
        .WillByDefault(action);
    
    • Matchery – określają warunki wywołania (np. ::testing::_ dla dowolnego argumentu, ::testing::Gt(5) dla wartości > 5);
    • Akcje – definiują reakcję atrapy (np. Return(42), Throw(error)).
      Przykład ustawienia domyślnej wartości zwracanej:
    ON_CALL(myMock, GetSize())
        .WillByDefault(Return(100));
    

    ON_CALL jest szczególnie użyteczny dla metod wywoływanych wielokrotnie lub w przypadku, gdy test skupia się na logice nie związanej z wszystkimi możliwymi scenariuszami. Działa globalnie na poziomie obiektu atrapy, co może prowadzić do konfliktów z EXPECT_CALL (o czym poniżej).

    Definiowanie oczekiwań z EXPECT_CALL

    Podstawowym mechanizmem weryfikacyjnym GMock jest EXPECT_CALL, który:

    1. Deklaruje wymaganie wywołania metody;
    2. określa warunki (argumenty, liczba wywołań);
    3. definiuje reakcje dla spełnionych warunków.
      Pełna składnia:
    EXPECT_CALL(mock_object, method_name(matchers))
        .Times(cardinality)        // oczekiwana liczba wywołań
        .InSequence(sequences...) // kolejność wywołań
        .WillOnce(action)         // akcja dla pierwszego pasującego wywołania
        .WillRepeatedly(action);  // akcja dla kolejnych wywołań
    

    Kluczowe klauzule

    • Cardinality –
    • Times(n) – dokładnie n wywołań,
    • AtLeast(n)/AtMost(n) – zakres wywołań,
    • pominięcie Times oznacza:
      EXPECT_CALL(mock, Foo()) // Times(1) - domyślnie
      EXPECT_CALL(mock, Bar())
          .WillOnce(Return(1))    // Times(1) - z jednym WillOnce
          .WillOnce(Return(2));   // Times(2) - dwa WillOnce
      
    • Akcje –
    • WillOnce – akcja wykonana raz dla pasującego wywołania,
    • WillRepeatedly – akcja dla wszystkich kolejnych wywołań.
      Przykład sekwencyjnego sterowania zwracanymi wartościami:
    
    EXPECT_CALL(turtle, GetX())
        .WillOnce(Return(100))    // pierwsze wywołanie: 100
        .WillOnce(Return(150))    // drugie wywołanie: 150
        .WillRepeatedly(Return(200)); // kolejne: 200
    

    Konflikty i interakcje między ON_CALL a EXPECT_CALL

    Problem – gdy ON_CALL i EXPECT_CALL konkurują dla tych samych wywołań, pierwszeństwo ma EXPECT_CALL. Jednak każde wywołanie niespełniające warunków EXPECT_CALL (np. inny argument) zostanie przekierowane do ON_CALL i oznaczone jako nieoczekiwane, generując błąd.
    Przykład problematyczny:

    ON_CALL(mock, Example(_)).WillByDefault(Return(0)); // domyślnie 0
    EXPECT_CALL(mock, Example(Ge(10)))              // oczekiwanie dla ≥10
        .WillRepeatedly(Return(5));
    // Test:
    FunctionUnderTest(15);   // spełnia EXPECT_CALL → OK
    FunctionUnderTest(3);    // niespełnia EXPECT_CALL, używa ON_CALL → BŁĄD!
    

    Rozwiązania –

    1. Użyj NiceMock lub StrictMock dla kontroli zgłaszania nieoczekiwanych wywołań;
    2. unikaj nadmiarowego ON_CALL w obecności EXPECT_CALL z wąskimi warunkami;
    3. definiuj EXPECT_CALL dla wszystkich przewidywanych wywołań, nawet trywialnych.

    Zaawansowane techniki i best practices

    Matchery argumentów

    Matchery pozwalają na elastyczne dopasowywanie argumentów:

    • _ – dowolna wartość,
    • Gt(n)/Lt(n) – porównania,
    • Eq(value) – równość,
    • złożone kombinacje (AllOf, AnyOf).
      Przykład:
    
    EXPECT_CALL(api, Send(AllOf(Gt(100), Lt(200))))
        .WillOnce(Return(SUCCESS));
    

    Kontrola kolejności wywołań

    Sekwencje wymuszają kolejność:

    Sequence s1;
    EXPECT_CALL(mock, A()).InSequence(s1);
    EXPECT_CALL(mock, B()).InSequence(s1); // B wywołane po A
    

    Dla niezależnych grup:

    SequenceSet ss;
    auto s1 = ss.AddNew(); // sekwencja 1
    auto s2 = ss.AddNew(); // sekwencja 2
    EXPECT_CALL(mock, C()).InSequenceSet(ss); // po wszystkich
    

    Pułapki i zalecenia

    1. Kolejność deklaracji – EXPECT_CALL musi poprzedzać wywołania kodu;
    2. Undefined behavior – zmiana oczekiwań (EXPECT_CALL) po wywołaniu metody jest niezdefiniowana;
    3. Nadmiarowe wywołania – użyj RetiresOnSaturation() dla oczekiwań, które nie powinny być używane wielokrotnie;
    4. Izolacja – każdy test powinien definiować własne oczekiwania, unikając stanu globalnego.

    Podsumowanie i wnioski

    ON_CALL i EXPECT_CALL są fundamentami kontroli zachowań obiektów atrap w GMock. Podczas gdy ON_CALL definiuje domyślne reakcje, EXPECT_CALL służy do weryfikacji specyficznych interakcji z atrapą. Kluczowe różnice:

    Cecha ON_CALL EXPECT_CALL
    Cel Domyślne zachowanie Walidacja wywołań
    Wymagalność Opcjonalny Obowiązkowy dla weryfikacji
    Kardynalność Brak kontroli Ścisła kontrola (Times())
    Priorytet Niższy Wyższy (nadpisuje ON_CALL)

    Praktyczne zalecenia:

    • Używaj ON_CALL ostrożnie, gdy domyślne zachowanie jest naprawdę globalnie potrzebne;
    • preferuj EXPECT_CALL dla jasnej ekspresji wymagań testowych;
    • unikaj mieszania ON_CALL i EXPECT_CALL dla tych samych metod bez ścisłej kontroli warunków;
    • wykorzystuj matchery dla elastyczności i sekwencje dla złożonych scenariuszy.

    Dzięki tej wiedzy programiści mogą efektywnie izolować testowany kod od zależności, tworząc niezawodne i utrzymywalne testy jednostkowe w C++.

    Polecane:

    • Wyszukiwanie testów w Google Test – metody i narzędzia
    • Historia wyrażeń lambda w C++ od C++03 do C++20
    • Zaawansowane scenariusze z std::visit i wieloma wariantami
    • Praktyczne użycie std::optional w nowoczesnym C++
    • Makefile od podstaw – składnia, najczęstsze pułapki, automatyzacja i przyspieszanie budowania
    Share. Facebook Twitter LinkedIn Email Copy Link
    Oskar Klimkiewicz
    • Website

    Inżynier oprogramowania specjalizujący się w C++, absolwent Wydziału Elektroniki i Technik Informacyjnych Politechniki Warszawskiej. Od ponad 8 lat projektuje i rozwija systemy o wysokiej dostępności, głównie dla branży fintech i IoT. PS. Zdjęcie wyretuszowane przez AI :)

    Podobne artykuły

    Maszyna stanów oparta o std::variant

    8 Mins Read

    Tablice w C++ od podstaw – deklaracja, inicjalizacja, iteracja i typowe pułapki

    4 Mins Read

    std::deque w C++ – kiedy wybrać dwukierunkową kolejkę zamiast vectora

    4 Mins Read
    Leave A Reply Cancel Reply

    Oglądaj, słuchaj, ćwicz - zdobywaj nowe umiejętności online
    Nie przegap

    Jak podłączyć telefon do monitora? Przewodowe i bezprzewodowe sposoby

    Oskar Klimkiewicz6 Mins Read

    Podłączenie telefonu do monitora to jedna z najistotniejszych innowacji ery mobilnej, umożliwiająca przeniesienie doświadczeń z…

    Co można wrzucić w koszty firmy jednoosobowej? Lista i praktyczne przykłady

    2025-12-03

    Jak podłączyć okulary VR do PS4? Poradnik podłączenia i konfiguracji

    2025-12-02

    Jak zapobiec wyciekom danych firmowych?

    2025-11-28
    Social media
    • Facebook
    • Twitter
    • LinkedIn
    O nas
    O nas

    CPP Polska to serwis internetowy poświęcony technologii, programowaniu, IT, biznesowi i finansom. Znajdziesz tu porady, wskazówki i instrukcje dla wszystkich czytelników IT & Tech & Biz.

    Facebook X (Twitter) LinkedIn RSS
    Najnowsze

    Jak podłączyć telefon do monitora? Przewodowe i bezprzewodowe sposoby

    2025-12-08

    Co można wrzucić w koszty firmy jednoosobowej? Lista i praktyczne przykłady

    2025-12-03

    Jak podłączyć okulary VR do PS4? Poradnik podłączenia i konfiguracji

    2025-12-02
    Popularne

    Skrajnie niepotrzebne, skrajne przypadki w C++

    2025-06-28

    Wyszukiwanie testów w Google Test – metody i narzędzia

    2025-06-28

    Czy C jest wolniejszy od C++? Zero-cost abstraction w praktyce

    2025-06-28
    © 2025 CPP Polska. Wszelkie prawa zastrzeżone.
    • Lista publikacji
    • Współpraca
    • Kontakt

    Type above and press Enter to search. Press Esc to cancel.