Programování

Jak používat Moq pro usnadnění testování jednotek v C #

Často musíme psát jednotkové testy pro kód, který přistupuje k externímu prostředku, jako je databáze nebo souborový systém souborů. Pokud takové prostředky nejsou k dispozici, jediným způsobem, jak zajistit, že testy mohou být provedeny, je vytvoření falešných objektů. V podstatě můžete pomocí falešných implementací těchto základních závislostí otestovat interakci mezi testovanou metodou a jejími závislostmi. Tři z nejpopulárnějších posměšných rámců pro vývojáře .Net jsou Rhino Mocks, Moq a NMock.

Mezi nimi může být Moq nejvíce flexibilní a snadno použitelný. Rámec Moq poskytuje elegantní způsob nastavení, testování a ověřování falešných zpráv. Tento článek představuje diskusi o Moq a o tom, jak jej lze použít k izolaci jednotek kódu z jejich závislostí.

Začínáme s Moq

Můžete použít Moq k vytvoření falešných objektů, které simulují nebo napodobují skutečný objekt. Moq lze použít k zesměšňování tříd i rozhraní. Existuje však několik omezení, která byste měli znát. Třídy, které mají být zesměšňovány, nemohou být statické ani zapečetěné a zesměšňovaná metoda by měla být označena jako virtuální. (Všimněte si, že existují omezení těchto omezení. Statickou metodu byste mohli zesměšňovat například tím, že využijete výhod návrhového vzoru adaptéru.)

Prvním krokem při používání Moq je instalace, abyste jej mohli použít v projektu testování jednotky. Můžete si stáhnout Moq z GitHubu a přidat odkazy podle potřeby. Dávám však přednost instalaci Moq přes NuGet, protože je jednodušší a méně pravděpodobné, že chybět odkazy. Moq můžete nainstalovat pomocí následujícího příkazu na příkazovém řádku NuGet.

Instalační balíček Moq

Jak zesměšňovat rozhraní pomocí Moq

Začněme zesměšňováním rozhraní. Syntaxe pro vytvoření falešného objektu pomocí třídy Mock je uvedena níže.

Mock mockObjectType = new Mock ();

Nyní zvažte následující rozhraní s názvem IAuthor.

veřejné rozhraní IAuthor

    {

int Id {get; soubor; }

řetězec FirstName {get; soubor; }

řetězec Příjmení {get; soubor; }

    }

Pomocí rámce Moq můžete vytvořit falešný objekt, nastavit hodnoty vlastností, zadat parametry a vrátit hodnoty na volání metody. Následující fragment kódu ukazuje, jak můžete vytvořit instanci z rozhraní IAuthor pomocí Moq.

var mock = new Mock ();

Všimněte si, že třída Mock patří do rámce Moq a obsahuje obecný konstruktor, který přijímá typ rozhraní, které chcete vytvořit. Moq využívá výrazů lambda, delegátů a generik. Díky tomu je používání rámce velmi intuitivní.

Následující fragment kódu ukazuje, jak můžete zesměšňovat rozhraní IAuthor a poskytovat vlastnosti zesměšňované instance s příslušnými hodnotami. Všimněte si, jak používáme Assert k ověření hodnot vlastností zesměšňované instance.

var autor = nový Mock ();

author.SetupGet (p => p.Id). Returns (1);

author.SetupGet (p => p.FirstName). Returns („Joydip“);

author.SetupGet (p => p.LastName) .Returns („Kanjilal“);

Assert.AreEqual („Joydip“, autor.Object.FirstName);

Assert.AreEqual („Kanjilal“, autor.Object.LastName);

Jak zesměšňovat metody pomocí Moq

Podívejme se nyní na následující třídu s názvem Article. Třída Article obsahuje pouze jednu metodu nazvanou GetPublicationDate, která přijímá ID článku jako parametr a vrací datum publikace článku.

článek veřejné třídy

    {

veřejný virtuální DateTime GetPublicationDate (int articleId)

        {

hodit nový NotImplementedException ();

        }

    }

Vzhledem k tomu, že metoda GetPublicationDate ještě není implementována ve třídě Article, byla metoda zesměšňována tak, aby vrátila aktuální datum jako datum publikace, jak je ukázáno v níže uvedeném fragmentu kódu.

var mockObj = new Mock ();
mockObj.Setup (x => x.GetPublicationDate (It.IsAny ())). Returns ((int x) => DateTime.Now);

Metoda Setup se používá k definování chování metody, která se mu předává jako parametr. V tomto příkladu se používá k definování chování metody GetPublicationDate. Volání na It.IsAny () znamená, že metoda GetPublicationDate přijme parametr typu celé číslo; To odkazuje na statickou třídu. Metoda Returns se používá k určení návratové hodnoty metody, která je zadána ve volání metody Setup. V tomto příkladu se metoda Returns používá k určení návratové hodnoty metody jako aktuálního systémového data.

Moq umožňuje ověřit, zda byla volána konkrétní metoda nebo vlastnost. Následující fragment kódu to ilustruje.

mockObj.Verify (t => t.GetPublicationDate (It.IsAny ()));

Tady používáme metodu Verify k určení, zda byl GetPublicationDate volán na falešném objektu.

Jak zesměšňovat metody základní třídy pomocí Moq

Zvažte následující část kódu. Máme zde dvě třídy - třídu RepositoryBase a třídu AuthorRepository, která ji rozšiřuje.

veřejná abstraktní třída RepositoryBase

{

public virtual bool IsServiceConnectionValid ()

    {

// Nějaký kód

    }

}

veřejná třída AuthorRepository: RepositoryBase

{

public void Uložit ()

    {

if (IsServiceConnectionValid ())

        {

// Nějaký kód

        }

    }

}

Nyní předpokládejme, že chceme zkontrolovat, zda je připojení k databázi platné. Možná však nebudeme chtít otestovat celý kód uvnitř metody IsServiceConnectionValid. Například metoda IsServiceConnectionValid může obsahovat kód, který se týká knihovny jiného výrobce. Nechtěli bychom to otestovat, že? Zde přichází na pomoc metoda CallBase v Moq.

V situacích, jako je tato, kde máte metodu v základní třídě, která byla přepsána v zesměšňovaném typu, a potřebujete zesměšňovat pouze základní verzi přepsané metody, můžete kreslit na CallBase. Následující fragment kódu ukazuje, jak můžete vytvořit částečný falešný objekt třídy AuthorRepository nastavením CallBase vlastnosti na true.

var mockObj = new Mock () {CallBase = true};

mockObj.Setup (x => x.IsServiceConnectionValid ()). Vrací (true);

Rámec Moq usnadňuje vytváření falešných objektů, které napodobují chování tříd a rozhraní pro testování, pouze s funkcemi, které potřebujete. Další informace o testování s předstíráním najdete v tomto skvělém článku od Martina Fowlera.