mockowanie metody lokalnego obiektu

0

Witam
Czy ktoś wie czy da radę tutaj jakoś zamokowac metodę lokalnego obiektu? Chciałbym zrobić na niej EXPECT_CALLa (sprawdzać czy się wywołuje). Czy jedyne wyjście to rezygnacja z lokalnej zmiennej 'driver' i stworzenie pola klasy -> w tym wypadku dalej to już łatwo zamokować metodę i wykonac EXPECT_CALLa. Ale pytanie czy da się jakoś nie zmieniac implementacji kodu źródłowego - nie lubię jak na potrzeby unit testów muszę zmieniać implementacje klasy bo naprawde ten obiekt nie jest mi do szczęścia potrzebny w ciele klasy. Ale jednocześnie chciałbym sprawdzić w teście czy metoda się wywołuje. Czy poza ifdefami da się cos tu zdziałać?

class KlasaGlowna
{
    public:
	    KlasaGlowna();
        virtual ~KlasaGlowna();

    protected:
        virtual Subclass getDriver();
};


void KlasaGlowna::TestowanaMetoda()
{
	Subclass driver = getDriver();
    try
    {
    	driver.metodaNaKtorejExpectCallaRobimyBySprCzySieWywoluje();
        .....
    }
    catch(..)
    {
        ....
    }
}
Subclass KlasaGlowna::getDriver() //taka implementacja 'Subclass& KlasaGlowna::getDriver()' nie rpzejdzie bo nie mozna zwrocić referencji do tymczasowego obiektu
{
    return Subclass();
}

Kombinowałem ze stworzeniem dodatkowej metody 'getDriver()' dla której planowałem w mocku klasy zrobić nowa implementację i zwracać mocka klasy Subclass, ale nie przechochodzi test z wiadomych względów.

0

Skoro chcesz zamockować metodę lokalnego obiektu to sam lokalny obiekt musi być mockiem. Standardowe podejście polega na użyciu dependency injection do przekazywania mock-ów do testowanego obiektu. Zamiast tworzenia dodatkowej metody getDriver po prostu wstrzyknij drivera przez konstruktor do KlasaGlowna.

Ale pytanie czy da się jakoś nie zmieniac implementacji kodu źródłowego - nie lubię jak na potrzeby unit testów muszę zmieniać implementacje klasy bo naprawde ten obiekt nie jest mi do szczęścia potrzebny w ciele klasy.

Właśnie o to chodzi żeby nie zmieniać. Na etapie designu musisz zdecydować z jakimi klasami twoja klasa KlasaGlowna będzie współpracować.
Wyłapujesz wszystkie zewnętrzne zależności i przez DI wstrzykujesz je wszystkie za jednym zamachem przez konstruktor, nie zaszkodzi przez std::shared_ptr.
W tym momencie dopiero tworzysz implementację, "ważne" obiekty masz już w polach testowanego obiektu, więc można je bez problemu zamockować i z zewnątrz sterować zachowaniem.
A lokalne obiekty są "nieważne" i możesz ograniczyć się jedynie do walidacji ich zawartości (przez EXPECT_CALL-a) w momencie przekazywania ich do zamockowanych metod tych "ważnych".

Czy poza ifdefami da się cos tu zdziałać?

Niech cię ręka boska broni przed czymś takim...

Tutaj masz fajne przykłady z żółwiami, które pokazują w działaniu podejście które wyżej opisałem:
https://github.com/google/googletest/blob/master/googlemock/docs/ForDummies.md

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