Wyobraźmy sobie sytuację w której mamy jakąś aplikację, która jest internetowym sklepem. W
aplikacji takiej powinniśmy móc dodać coś do koszyka zakupowego i oczywiście zobaczyć w każdej chwili co znajduje się w naszym koszyku.
public class ShoppingCartController
{
private ShoppingCartService _shoppingCartService;
public ShoppingCartController()
{
_shoppingCartService = new ShoppingCartService();
}
public ShoppingCart GetCart()
{
ShoppingCart cart = _shoppingCartService.GetContents();
return cart;
}
public ShoppingCart AddItemToCart(int itemId, int quantity)
{
ShoppingCart cart = _shoppingCartService.AddItemToCart(itemId, quantity);
return cart;
}
}
Zakładamy że za pomocą klasy ShoppingCartService aplikacja łączy się z jakąś usługą. Przestowanie tego kawałka kodu polegałoby na napisaniu metody testującej w której wywołujemy po prostu metody powyższej klasy. Załóżmy teraz, że chcelibyśmy napisać testy, które nie będą łączyć się z usługą. Co trzeba by było zrobić. Najprostszym sposobem jest stworzenie fake klasy ShoppingCartService nazwijmy ją ShoppingCartServiceFake. Zmodyfikujmy kod aby zadanie to było możliwe do wykonania. Na początku, stwórzmy interfejs IShoppingCartService i zmodyfikujmy nieco kod tak jak poniżej:
public interface IShoppingCartService
{
ShoppingCart GetContents();
ShoppingCart AddItemToCart(int itemId, int quantity);
}
public class ShoppingCartController
{
private IShoppingCartService _shoppingCartService;
public ShoppingCartController()
{
_shoppingCartService = new ShoppingCartService();
}
public ShoppingCart GetCart()
{
ShoppingCart cart = _shoppingCartService.GetContents();
return cart;
}
public ShoppingCart AddItemToCart(int itemId, int quantity)
{
ShoppingCart cart = _shoppingCartService.AddItemToCart(itemId, quantity);
return cart;
}
}
Zakładamy teraz że ShoppingCartService implementuje interface IShoppingCartService. Teraz
dopismy klasę fake
Ostatnim elementem jest dopisanie nowego konstruktora do klasy ShoppingCartController:
public ShoppingCartController(IShoppingCartService shoppingCartService)
{
_shoppingCartService = shoppingCartService;
}
Teraz możemy napisać test:
[TestClass]
public class ShoppingCartControllerTests
{
[TestMethod]
public void GetCartSmokeTest()
{
ShoppingCartController controller =
new ShoppingCartController(new ShoppingCartServiceFake());
ActionResult result = controller.GetCart();
Assert... //sprawdzamy sobie tutaj jakiś warunek np. ilośc itemów
}
}
Jak widać na potrzeby testu jednostkowego tworzymy instancję obiektu ShoppingCartController z
fałszywym obiektem, który udaje klasę łączącą się z usługą.
Teraz załóżmy sytuację taką w której chcielibyśmy móc w jednym miejscu skonfigurować, która klasa
– czy ta która się łączy z usługą czy fałszywa – jest podawana do konstruktora:
public ShoppingCartController(IShoppingCartService shoppingCartService)
{
_shoppingCartService = shoppingCartService;
}
I z pomocą tutaj przychodzi nam StructureMap. Dll można pobrać ze strony: https://github.com/
structuremap/structuremap/downloads. Po pobraniu wystarczy dodać referencję do pliku
StructureMap.dll.
Teraz mając konstruktor przedstawiony powyżej piszemy nowy bezparametrowy
public ShoppingCartController() : this(ObjectFactory.GetInstance<
IshoppingCartService>
{
_shoppingCartService = shoppingCartService;
}
Teraz aby ObjectFaktory zwrócił nam odpowiedni obiekt klasy musimy napisać BootStrapper –
specjalną klasę, która odpowiednio skonfiguruje nam StructureMap:
public class DependencyRegistry : Registry
{
public DependencyRegistry()
{
For().Use();
//Lub jeśli będziemy chceli używać klasy, która naprawdę łączy
się z usługą: For().Use();
}
}
public static class BootStrapper
{
public static void Bootstrap()
{
);
}
}
ObjectFactory.Initialize(x => x.AddRegistry(new DependencyRegistry())
Teraz w metodzie main klasy program wpisać: BootStrapper.BootStrap() i podczas wywołania
nowego kontruktora do klasy zostanie przekazany odpowiedni obiekt klasy dziedziczącej po
interfejsie IShoppingCartService
0 komentarze:
Prześlij komentarz