Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Az egységtesztek írásának számos előnye van. Segítenek a regresszióban, dokumentációt nyújtanak, és megkönnyítik a jó tervezést. Ha azonban az egységtesztek nehezen olvashatók és törékenyek, a kódbázison is pusztíthatnak. Ez a cikk néhány ajánlott eljárást ismertet a .NET Core- és .NET Standard-projektek támogatásához szükséges egységtesztek tervezéséhez. Elsajátíthatja a technikákat, hogy a tesztek rugalmasak és könnyen érthetőek legyenek.
John Reese írta, külön köszönet Roy Osherove-nak
Az egységtesztelés előnyei
A következő szakaszok számos okot ismertetnek a .NET Core- és .NET Standard-projektek egységtesztjeinek írására.
Kevesebb idő a funkcionális tesztek elvégzésére
A funkcionális tesztek költségesek. Ezek általában magukban foglalják az alkalmazás megnyitását és az Ön (vagy valaki más) által követendő lépések sorozatát a várt viselkedés ellenőrzéséhez. Előfordulhat, hogy ezek a lépések nem mindig ismertek a tesztelő számára. A teszt elvégzéséhez fel kell lépniük egy olyan személyhez, aki jártosabb a területen. Maga a tesztelés másodpercekig is eltarthat a triviális változások esetén, vagy a nagyobb módosítások esetén percekig. Végül ezt a folyamatot meg kell ismételni a rendszerben végzett minden módosításnál. Az egységtesztek viszont ezredmásodpercig is eltarthatnak, egy gombnyomással futtathatók, és nem feltétlenül igényelnek a rendszer széles körű ismereteit. A tesztfuttató határozza meg, hogy a teszt sikeres vagy sikertelen lesz-e, nem pedig az egyén.
Regresszió elleni védelem
A regressziós hibák olyan hibák, amelyeket az alkalmazás módosításakor vezetnek be. Gyakori, hogy a tesztelők nem csak az új funkciójukat tesztelik, hanem a korábban meglévő funkciókat is tesztelik annak ellenőrzéséhez, hogy a meglévő funkciók továbbra is a várt módon működnek-e. Az egységteszteléssel a teljes tesztcsomagot újrafuttathatja minden build után, vagy akár egy kódsor módosítása után is. Ez a megközelítés segít abban, hogy az új kód ne szegje meg a meglévő funkciókat.
Végrehajtható dokumentáció
Lehet, hogy nem mindig nyilvánvaló, hogy egy adott módszer mit tesz, vagy hogyan viselkedik adott bemenettel. Felteheti magának a kérdést: Hogyan működik ez a módszer, ha egy üres sztringet vagy null értéket adok át? Ha jól elnevezett egységtesztekkel rendelkezik, minden tesztnek egyértelműen meg kell magyaráznia egy adott bemenet várható kimenetét. Emellett a tesztnek képesnek kell lennie annak ellenőrzésére, hogy valóban működik-e.
Kevésbé kapcsolt kód
Ha a kód szorosan összekapcsolódik, nehéz lehet egységtesztelni. Ha nem hoz létre egységteszteket az éppen írt kódhoz, az összekapcsolás kevésbé nyilvánvaló. A kód tesztjeinek írása természetesen szétválasztja a kódmodulokat, mert különben nehezebb tesztelni.
A jó egységtesztek jellemzői
A jó egységtesztet számos fontos jellemző határozza meg:
- Gyors: Nem ritka, hogy az érett projektek több ezer egységteszttel rendelkeznek. Az egységtesztek futtatása kevés időt vesz igénybe. Ezredmásodpercek.
- Izolált: Az egységtesztek önállóak, elkülönítve futtathatók, és nem függenek semmilyen külső tényezőtől, például fájlrendszertől vagy adatbázistól.
- Megismételhető: Az egységtesztek futtatásának összhangban kell lennie az eredményeivel. A teszt mindig ugyanazt az eredményt adja vissza, ha nem módosít semmit a futtatások között.
- Önellenőrzés: A tesztnek automatikusan észlelnie kell, hogy az emberi beavatkozás nélkül sikeres vagy sikertelen volt-e.
- Idő: Az egységtesztek írása nem vehet aránytalanul hosszú időt a tesztelt kódhoz képest. Ha azt tapasztalja, hogy a kód tesztelése nagy időt vesz igénybe a kód írásához képest, fontolja meg a tesztelhetőbb kialakítást.
Kódlefedettség és kódminőség
A magas kódlefedettségi arány gyakran magasabb szintű kódhoz van társítva. Maga a mérés azonban nem tudja meghatározni a kód minőségét. A túlságosan ambiciózus kódlefedettségi százalékcél beállítása kontraproduktív lehet. Fontolja meg egy több ezer feltételes ágat tartalmazó összetett projektet, és tegyük fel, hogy 95% kódlefedettségi célt tűz ki célul. A projekt jelenleg 90% kódlefedettségi kapcsolatot tart fenn. A fennmaradó 5% minden szélsőséges esetének figyelembevétele rengeteg időt igényelhet, és a javasolt érték gyorsan csökkenhet.
A magas kódlefedettség nem a sikeresség jelzője, és nem jelenti a kód minőségét. Ez csak az egységtesztek által lefedett kód mennyiségét jelöli. További információ: egységtesztelési kódlefedettség.
Egységtesztelési terminológia
Az egységtesztelés során gyakran több kifejezést is használnak: hamis, hamis és csonkos. Sajnos ezek a kifejezések helytelenül alkalmazhatók, ezért fontos megérteni a helyes használatot.
Hamis: A hamis egy általános kifejezés, amely egy csonk vagy egy mintaobjektum leírására használható. Attól függ, hogy az objektum csonk vagy mintapéldány-e, attól függ, hogy milyen környezetben használják az objektumot. Más szóval, a hamis lehet egy csonk vagy egy hamisítvány.
Mock: A modellobjektum egy hamis objektum a rendszerben, amely eldönti, hogy egy egységteszt sikeres-e vagy sem. A próba hamisként kezdődik, és hamis marad, amíg be nem lép egy
Assert
műveletbe.Csonk: A csonk egy létező függőség (vagy közreműködő) szabályozható helyettesítője a rendszerben. Egy helyettesítő használatával anélkül tesztelheti a kódját, hogy közvetlenül kezelnie kellene a függőséget. Alapértelmezés szerint a csonk hamisítványként kezdődik.
Vegye figyelembe a következő kódot:
var mockOrder = new MockOrder();
var purchase = new Purchase(mockOrder);
purchase.ValidateOrders();
Assert.True(purchase.CanBeShipped);
Ez a kód egy makettnek nevezett csonkot jelenít meg. Ebben a forgatókönyvben azonban a csonk valóban csonk. A kód célja, hogy a megrendelést a Purchase
(a tesztelendő rendszer) objektum példányosításának eszközeként továbbítsa. Az osztály neve MockOrder
félrevezető, mert a sorrend egy csonk, és nem egy minta.
Az alábbi kód pontosabb kialakítást mutat be:
var stubOrder = new FakeOrder();
var purchase = new Purchase(stubOrder);
purchase.ValidateOrders();
Assert.True(purchase.CanBeShipped);
Amikor az osztályt átnevezik FakeOrder
-re, az osztály általánosabbá válik. Az osztály a teszteset követelményeinek megfelelően használható mintaként vagy csonkként. Az első példában az FakeOrder
osztály csonkként van használva, és a Assert
művelet során nem használják. A kód csak azért adja át az FakeOrder
osztályt az Purchase
osztálynak, hogy megfeleljen a konstruktor követelményeinek.
Ha az osztályt mintaként szeretné használni, frissítheti a kódot:
var mockOrder = new FakeOrder();
var purchase = new Purchase(mockOrder);
purchase.ValidateOrders();
Assert.True(mockOrder.Validated);
Ebben a kialakításban a kód ellenőrzi a hamis tulajdonságot (érvényesítve vele szemben), ezért az mockOrder
osztály egy makett.
Fontos
Fontos a terminológia helyes implementálása. Ha a csonkokat "mocks"-nak nevezed, más fejlesztők félreérthetnek a szándékaidat illetően.
A legfontosabb dolog, amire emlékezni kell a mockok és csonkok tekintetében, hogy a mockok olyanok, mint a csonkok, kivéve a Assert
folyamatot. Futtat Assert
műveleteket egy modellobjektumon, de nem egy csonkon.
Ajánlott eljárások
Az egységtesztek írásakor számos fontos ajánlott eljárást követhet. A következő szakaszok példákat mutatnak be, amelyek bemutatják, hogyan alkalmazhatja az ajánlott eljárásokat a kódra.
Az infrastruktúra-függőségek elkerülése
Az egységtesztek írásakor próbálja meg nem bevezetni az infrastruktúrától való függőségeket. A függőségek lassúvá és törékenysé teszik a teszteket, és az integrációs tesztek számára fenntartottnak kell lenniük. Ezeket a függőségeket elkerülheti az alkalmazásban az Explicit függőségek elvének követésével és a .NET-függőséginjektálás használatával. Az egységteszteket az integrációs tesztektől eltérő projektben is megtarthatja. Ez a megközelítés biztosítja, hogy az egységtesztelési projekt nem hivatkozik az infrastruktúra-csomagokra vagy függőségekre.
Tesztelnevezési szabványok követése
A teszt nevének három részből kell állnia:
- A tesztelt módszer neve
- A módszer tesztelésének forgatókönyve
- A forgatókönyv meghívásakor várható viselkedés
Az elnevezési szabványok azért fontosak, mert segítenek a teszt céljának és alkalmazásának kifejezésében. A tesztek nem csupán a kód működésének biztosítását teszik lehetővé. Emellett dokumentációt is nyújtanak. Csak az egységtesztek csomagjának megtekintésével képesnek kell lennie arra, hogy következtethessen a kód viselkedésére, és nem kell magát a kódot megvizsgálnia. Ezenkívül ha a tesztek sikertelenek, pontosan láthatja, hogy mely forgatókönyvek nem felelnek meg az elvárásainak.
eredeti kód
[Fact]
public void Test_Single()
{
var stringCalculator = new StringCalculator();
var actual = stringCalculator.Add("0");
Assert.Equal(0, actual);
}
Ajánlott eljárás alkalmazása
[Fact]
public void Add_SingleNumber_ReturnsSameNumber()
{
var stringCalculator = new StringCalculator();
var actual = stringCalculator.Add("0");
Assert.Equal(0, actual);
}
A tesztek rendezése
Az "Elrendezés, Cselekvés, Állítás" minta gyakori megközelítés az egységtesztek írására. Ahogy a neve is mutatja, a minta három fő feladatból áll:
- Rendezze el az objektumokat, hozza létre és konfigurálja őket szükség szerint
- Művelet egy objektumon
- Annak állítása , hogy valami a vártnak megfelelően van
Ha követi a mintát, egyértelműen elkülönítheti azt, amit tesztelnek, az Elrendezés és az Ellenőrzés feladatoktól. A minta emellett segít csökkenteni annak lehetőségét, hogy az állítások az Act tevékenységben lévő kóddal keveredjenek.
Az egységtesztek írásakor az olvashatóság az egyik legfontosabb szempont. Az egyes mintaműveleteket a teszten belül elkülönítve egyértelműen kiemeli a kód meghívásához szükséges függőségeket, a kód meghívásának módját és az érvényesíteni kívánt műveletet. Bár lehetséges egyes lépések kombinálása és a teszt méretének csökkentése, a teljes cél az, hogy a teszt a lehető legolvasottabb legyen.
eredeti kód
[Fact]
public void Add_EmptyString_ReturnsZero()
{
// Arrange
var stringCalculator = new StringCalculator();
// Assert
Assert.Equal(0, stringCalculator.Add(""));
}
Ajánlott eljárás alkalmazása
[Fact]
public void Add_EmptyString_ReturnsZero()
{
// Arrange
var stringCalculator = new StringCalculator();
// Act
var actual = stringCalculator.Add("");
// Assert
Assert.Equal(0, actual);
}
Minimális követelményeknek megfelelő tesztek írása
Az egységtesztek bemenetének a jelenleg tesztelt viselkedés ellenőrzéséhez szükséges legegyszerűbb információnak kell lennie. A minimalista megközelítés segít a teszteknek ellenállóbbá válni a kódbázis jövőbeli változásaival szemben, és a végrehajtás során a viselkedés ellenőrzésére összpontosít.
Az aktuális teszt elvégzéséhez szükségesnél több információt tartalmazó tesztek nagyobb eséllyel vezetnek be hibákat a tesztbe, és kevésbé egyértelművé tehetik a teszt szándékát. Tesztek írásakor a viselkedésre szeretne összpontosítani. A nem szükséges tulajdonságok beállítása a modelleken vagy indokolatlan értékek használata csak elvonja a figyelmet arról, amit megpróbál megerősíteni.
eredeti kód
[Fact]
public void Add_SingleNumber_ReturnsSameNumber()
{
var stringCalculator = new StringCalculator();
var actual = stringCalculator.Add("42");
Assert.Equal(42, actual);
}
Ajánlott eljárás alkalmazása
[Fact]
public void Add_SingleNumber_ReturnsSameNumber()
{
var stringCalculator = new StringCalculator();
var actual = stringCalculator.Add("0");
Assert.Equal(0, actual);
}
Kerüljük a varázsszavak használatát
A magic sztringek olyan sztringértékek, amelyeket közvetlenül az egységtesztekben, bármilyen kódhoz fűzött megjegyzés vagy kontextus nélkül használtak. Ezek az értékek kevésbé olvashatóvá és nehezebbé teszik a kód karbantartását. A mágikus sztringek zavart okozhatnak a tesztek olvasója számára. Ha egy sztring a szokásostól eltérően néz ki, felmerülhet a kérdés, hogy miért választottak ki egy adott értéket egy paraméterhez vagy visszatérési értékhez. Az ilyen típusú sztringértékek azt eredményezhetik, hogy valaki inkább a megvalósítás részleteivel foglalkozik, ahelyett hogy a tesztre összpontosítana.
Jótanács
Célként tűzze ki, hogy a lehető legtöbb szándékot fejezze ki az egységteszt kódjában. Ahelyett, hogy mágikus sztringeket használ, rendeljen hozzá minden rögzített értéket az állandókhoz.
eredeti kód
[Fact]
public void Add_BigNumber_ThrowsException()
{
var stringCalculator = new StringCalculator();
Action actual = () => stringCalculator.Add("1001");
Assert.Throws<OverflowException>(actual);
}
Ajánlott eljárás alkalmazása
[Fact]
void Add_MaximumSumResult_ThrowsOverflowException()
{
var stringCalculator = new StringCalculator();
const string MAXIMUM_RESULT = "1001";
Action actual = () => stringCalculator.Add(MAXIMUM_RESULT);
Assert.Throws<OverflowException>(actual);
}
A kódolási logika elkerülése az egységtesztekben
Az egységtesztek írásakor kerülje a manuális sztringösszefűzést, a logikai feltételeket, mint például a if
, while
, for
és switch
, valamint az egyéb feltételeket. Ha a tesztcsomagban logikát is tartalmaz, a hibák bevezetésének esélye jelentősen megnő. Az utolsó hely, ahol hibát szeretne találni, a tesztcsomagban található. A tesztek működéséhez magas szintű megbízhatóságra van szükség, különben nem bízhat bennük. A nem megbízható tesztek nem adnak értéket. Ha egy teszt meghiúsul, azt szeretné, hogy legyen olyan érzése, hogy valami nincs rendben a kóddal, és hogy nem hagyható figyelmen kívül.
Jótanács
Ha a logika hozzáadása a tesztben elkerülhetetlennek tűnik, érdemes lehet a tesztet két vagy több különböző tesztre felosztani a logikai követelmények korlátozása érdekében.
eredeti kód
[Fact]
public void Add_MultipleNumbers_ReturnsCorrectResults()
{
var stringCalculator = new StringCalculator();
var expected = 0;
var testCases = new[]
{
"0,0,0",
"0,1,2",
"1,2,3"
};
foreach (var test in testCases)
{
Assert.Equal(expected, stringCalculator.Add(test));
expected += 3;
}
}
Ajánlott eljárás alkalmazása
[Theory]
[InlineData("0,0,0", 0)]
[InlineData("0,1,2", 3)]
[InlineData("1,2,3", 6)]
public void Add_MultipleNumbers_ReturnsSumOfNumbers(string input, int expected)
{
var stringCalculator = new StringCalculator();
var actual = stringCalculator.Add(input);
Assert.Equal(expected, actual);
}
Segítő metódusok használata a Beállítás és a Lebontás helyett
Ha a tesztekhez hasonló objektumra vagy állapotra van szüksége, használjon inkább egy segédmetódust, mint a Setup
és Teardown
attribútumokat, ha azok léteznek. A segédmetódusokat több okból részesítik előnyben ezekkel az attribútumokkal szemben.
- Kevesebb zavart okoz a tesztek olvasásakor, mert minden kód látható az egyes teszteken belül.
- Kisebb az esély arra, hogy túl sokat vagy túl keveset állítson be az adott teszthez
- Kisebb az esély az állapot tesztek közötti megosztására, ami nem kívánt függőségeket hoz létre közöttük
Az egységtesztelési keretrendszerekben az attribútumot a Setup
tesztcsomag minden egyes egységtesztje előtt meghívja a program. Egyes programozók hasznosnak látják ezt a viselkedést, de gyakran felfúvódó és nehezen olvasható teszteket eredményeznek. Minden tesztnek általában különböző követelményei vannak a beállításhoz és a végrehajtáshoz. Sajnos az Setup
attribútum arra kényszeríti önt, hogy az egyes tesztekre pontosan ugyanazokat a követelményeket alkalmazza.
Megjegyzés
Az SetUp
és TearDown
attribútumok eltávolításra kerültek a xUnit 2.x és ezt követő verziókban.
eredeti kód
Ajánlott eljárás alkalmazása
private readonly StringCalculator stringCalculator;
public StringCalculatorTests()
{
stringCalculator = new StringCalculator();
}
[Fact]
public void Add_TwoNumbers_ReturnsSumOfNumbers()
{
var stringCalculator = CreateDefaultStringCalculator();
var actual = stringCalculator.Add("0,1");
Assert.Equal(1, actual);
}
// More tests...
// More tests...
[Fact]
public void Add_TwoNumbers_ReturnsSumOfNumbers()
{
var result = stringCalculator.Add("0,1");
Assert.Equal(1, result);
}
private StringCalculator CreateDefaultStringCalculator()
{
return new StringCalculator();
}
Több felvonásos tevékenység elkerülése
A tesztek írásakor próbáljon tesztenként csak egy Act feladatot belefoglalni. Az egyetlen jogi aktusos feladat végrehajtásának néhány gyakori megközelítése lehet például egy külön teszt létrehozása az egyes jogi aktusokhoz, vagy paraméteres tesztek használata. Az, hogy minden teszthez egyetlen feladatot használunk, több előnnyel jár:
- A teszt sikertelensége esetén könnyen felismerheti, hogy melyik Act-feladat meghiúsul.
- Biztosíthatja, hogy a teszt csak egyetlen esetre összpontosítson.
- Világos képet kap arról, miért buknak meg a tesztjei.
A több felvonásos tevékenységeket egyénileg kell érvényesíteni, és nem garantálható, hogy az összes helyességi tevékenység végrehajtva legyen. A legtöbb egységtesztelési keretrendszerben a rendszer automatikusan sikertelennek tekinti az összes további tesztet, miután egy igény szerinti feladat meghiúsult egy egységtesztben. A folyamat zavaró lehet, mert egyes működő funkciók hibásnak tekinthetők.
eredeti kód
[Fact]
public void Add_EmptyEntries_ShouldBeTreatedAsZero()
{
// Act
var actual1 = stringCalculator.Add("");
var actual2 = stringCalculator.Add(",");
// Assert
Assert.Equal(0, actual1);
Assert.Equal(0, actual2);
}
Ajánlott eljárás alkalmazása
[Theory]
[InlineData("", 0)]
[InlineData(",", 0)]
public void Add_EmptyEntries_ShouldBeTreatedAsZero(string input, int expected)
{
// Arrange
var stringCalculator = new StringCalculator();
// Act
var actual = stringCalculator.Add(input);
// Assert
Assert.Equal(expected, actual);
}
Privát metódusok ellenőrzése nyilvános módszerekkel
A legtöbb esetben nem kell privát metódust tesztelnie a kódban. A privát metódusok az implementáció része és soha nem léteznek elszigetelten. A fejlesztési folyamat egy bizonyos pontján bevezet egy nyilvánosan elérhető metódust, amely a magánmetódust a megvalósítás részeként hívja meg. Egységtesztek írásakor az a lényeg, hogy milyen eredményt ad a privát metódust meghívó nyilvános metódus.
Fontolja meg a következő kódforgatókönyvet:
public string ParseLogLine(string input)
{
var sanitizedInput = TrimInput(input);
return sanitizedInput;
}
private string TrimInput(string input)
{
return input.Trim();
}
A tesztelés szempontjából az első reakció az lehet, hogy meg kell írnia egy tesztet a TrimInput
módszerhez, hogy az a várt módon működjön. Lehetséges azonban, hogy a ParseLogLine
metódus nem várt módon módosítja az sanitizedInput
objektumot. Az ismeretlen viselkedés haszontalanná teheti a TrimInput
módszeren végzett tesztet.
Ebben a forgatókönyvben jobb teszt a nyilvánosan elérhető ParseLogLine
módszer ellenőrzése:
public void ParseLogLine_StartsAndEndsWithSpace_ReturnsTrimmedResult()
{
var parser = new Parser();
var result = parser.ParseLogLine(" a ");
Assert.Equals("a", result);
}
Ha privát metódussal találkozik, keresse meg a privát metódust meghívó nyilvános metódust, és írja a teszteket a nyilvános metódusra. Csak azért, mert egy privát metódus várt eredményt ad vissza, nem jelenti azt, hogy a privát metódust végül meghívó rendszer helyesen használja az eredményt.
Csonk statikus hivatkozásainak kezelése varratokkal
Az egységteszt egyik alapelve, hogy teljes mértékben ellenőriznie kell a vizsgált rendszert. Ez az elv azonban problémás lehet, ha az éles kód statikus hivatkozásokat (például DateTime.Now
) hív meg.
Vizsgálja meg a következő kódforgatókönyvet:
public int GetDiscountedPrice(int price)
{
if (DateTime.Now.DayOfWeek == DayOfWeek.Tuesday)
{
return price / 2;
}
else
{
return price;
}
}
Meg tud írni egy egységtesztet ehhez a kódhoz? Megpróbálhat érvényességi feladatot futtatni a price
következőn:
public void GetDiscountedPrice_NotTuesday_ReturnsFullPrice()
{
var priceCalculator = new PriceCalculator();
var actual = priceCalculator.GetDiscountedPrice(2);
Assert.Equals(2, actual)
}
public void GetDiscountedPrice_OnTuesday_ReturnsHalfPrice()
{
var priceCalculator = new PriceCalculator();
var actual = priceCalculator.GetDiscountedPrice(2);
Assert.Equals(1, actual);
}
Sajnos gyorsan rájön, hogy problémák merülnek fel a teszttel kapcsolatban:
- Ha a tesztcsomag kedden fut, a második teszt sikeres lesz, de az első teszt meghiúsul.
- Ha a tesztcsomag bármelyik másik napon fut, az első teszt sikeres lesz, de a második teszt sikertelen lesz.
A problémák megoldásához be kell vezetnie egy varratot a termelési kódba. Az egyik megközelítés az, hogy a vezérelni kívánt kódot egy interfészbe csomagolja, és hagyja, hogy az éles kód attól az interfésztől függjön.
public interface IDateTimeProvider
{
DayOfWeek DayOfWeek();
}
public int GetDiscountedPrice(int price, IDateTimeProvider dateTimeProvider)
{
if (dateTimeProvider.DayOfWeek() == DayOfWeek.Tuesday)
{
return price / 2;
}
else
{
return price;
}
}
A tesztcsomag új verzióját is meg kell írnia:
public void GetDiscountedPrice_NotTuesday_ReturnsFullPrice()
{
var priceCalculator = new PriceCalculator();
var dateTimeProviderStub = new Mock<IDateTimeProvider>();
dateTimeProviderStub.Setup(dtp => dtp.DayOfWeek()).Returns(DayOfWeek.Monday);
var actual = priceCalculator.GetDiscountedPrice(2, dateTimeProviderStub);
Assert.Equals(2, actual);
}
public void GetDiscountedPrice_OnTuesday_ReturnsHalfPrice()
{
var priceCalculator = new PriceCalculator();
var dateTimeProviderStub = new Mock<IDateTimeProvider>();
dateTimeProviderStub.Setup(dtp => dtp.DayOfWeek()).Returns(DayOfWeek.Tuesday);
var actual = priceCalculator.GetDiscountedPrice(2, dateTimeProviderStub);
Assert.Equals(1, actual);
}
Most a tesztcsomag teljes mértékben szabályozhatja az DateTime.Now
értéket, és bármilyen értéket megcsonkíthat a metódusba való behíváskor.