2010-01-28 18 views
6

Szukam sposobów na zwięzłość.Uzyskiwanie SUCHA z Rhino Mocks

public class MyTests 
{ 
    IPresenter presenter; 

    [SetUp] 
    public void SetUp() 
    { 
     presenter = MockRepository.GenerateStub<IPresenter>(); 
    } 

    ... 
} 

W szczególności ponowne określenie typu podczas tworzenia makiety wydaje się zbędne. Na przykład mogę napisać to w ten sposób i użyć refleksji uzyskać rodzaj i stworzyć zalążek automatycznie:

public class MyTests 
{ 
    IPresenter presenter; 

    [SetUp] 
    public void SetUp() 
    { 
     Stub(x => x.presenter); 
    } 

    void Stub(Expression<Func<MyTests, object>> expression) 
    { 
     ... 
    } 
} 

to będzie działać, ale kompilator nie może wykryć, że prezenter jest przypisany i rozpoczyna wydawanie ostrzeżeń. To także sprawia, że ​​ReSharper jest bardzo nieszczęśliwy.

Czy ktoś może zaproponować lepsze podejście?

Odpowiedz

5

Może to być kontrowersyjne, ale wolę czytelność, a nie DRY-ność * w testach jednostkowych.

Innymi słowy, metody ustawiania nie występują w moich testach jednostkowych. Są używane tylko do testów integracyjnych. Sądzę, że również ta postawa brzmi: XUnit.NET.

Więc, aby odpowiedzieć na twoje pytanie, naprawdę nie martwiłbym się ustawianiem fałszywych prezenterów w każdym z twoich testów, które go wymagają. Niektóre testy mogą nie wymagać fałszywego prezentera, dlatego posiadanie jednej konfiguracji przed uruchomieniem testu nie jest konieczne.

** Naturalnie, moja jednostka testuje span, mówiąc średnio dziesięć linii, jeśli to się zwiększa lub zakres konfiguracji testu (po AAA - Rozmieść, Akt Asembler) jest duży, tylko wtedy usunę duplikację i utworzę pomocnika metody. Aby usunąć ten punkt, dla czystszych testów można utworzyć podstawową klasę testową, która zawiera metody pomocnicze i inny skonfigurowany kod. *

+1

W większości się z tym zgadzam (stąd +1), ale chciałbym również zasugerować, że możesz stworzyć wewnętrzną klasę do testów z mockami, jeśli będziesz miał dużo przypadków testowych z ich użyciem. – jonnii

+0

@jonni - Pobiłeś mnie do mojej edycji. Ale zgadzam się. – Finglas

+0

@finglas To jest okrąg porozumienia. Patrzymy sobie nawzajem na grzbiet;) – jonnii

3

Tak, nie używaj w ogóle [Setup] i zmiennych członkowskich, zamiast tego napisz Fixture Objects metodami tworzenia.

Obiekt Fixture po prostu przytrzyma odpowiednią próbę i inne części Urządzenia.

Osobiście korzystam AutoFixture as a Fixture Object i go skonfigurować jako Auto-Mocking Container do rozruchu, więc nie trzeba pisać żadnego kodu mock chyba muszę jednoznacznie określić pewne zachowania.

Oto ostatnie testy jednostkowe próbki:

[TestMethod] 
public void DeleteProductWillDeleteProductFromRepository() 
{ 
    // Fixture setup 
    var fixture = new ServiceFixture(); 
    var id = fixture.CreateAnonymous<int>(); 
    var repMock = fixture.FreezeMoq<ProductRepository>(); 

    var sut = fixture.CreateAnonymous<ProductManagementService>(); 
    // Exercise system 
    sut.DeleteProduct(id); 
    // Verify outcome 
    repMock.Verify(r => r.DeleteProduct(id)); 
    // Teardown 
} 

W tym przypadku repMock jest tworzony przez Min, ale mogłem ustawić go używać Rhino Mocks zamiast.

+1

bez [Setup] lub [przerywaniem] xUnit ftw! – mxmissile

+0

Wymieniasz zmienną składową + inicjator dla dodatkowej konfiguracji w każdej metodzie, która będzie sumować się z więcej niż kilkoma testami. Auto kpiny to coś, na co powinienem patrzeć, dziękuję. –

0

To ogólny ból z C#, że nie wywnioskuje on typu z wynik metody (w przeciwieństwie do Javy) i jest bolesny w wielu sytuacjach (wystarczy podać inny przykład, w którym chcesz zaimplementować metodę deserialisingu). Osobiście nie lubię używać słowa kluczowego var, ponieważ chcę dokładnie zobaczyć, jaki jest typ moich obiektów, wolałbym pominąć nazwę typu w szablonie.

W każdym razie, jeśli moje testy są dobre i małe, staram się zainicjować wszystkie mocks wewnątrz każdego testu. W ten sposób możesz spojrzeć na każdy test w oderwaniu od innych testów i od razu zobaczyć, co się tam dzieje. Jeśli zaczną robić się długo, po prostu użyję paskudnego sposobu wklejenia na początku twojego pytania.

1

Michael Feathers ma znakomity widok na ten temat (zobacz jego prezentację http://www.ndc2010.no/index.aspx?id=361621).Twórz konstruktorów i używaj tego w testach zamiast wszelkiego rodzaju rzeczy instalacyjnych.

odczuwalna:

//The Class to Test 
    public class ObjectY 
    { 
     public string DoThis(IObjectX objectX) 
     { 
      return objectX.id + objectX.name; 
     } 
    } 


    [Test] 
    //The test 
    public void CreaeteTestData() 
    { 
     //Almost prosa style creation of test data 
     var testData = new ObjectXBuilder().WithId(123).WithName("ABC").Build(); 

     Assert.That(new ObjectY().DoThis(testData), Is.EqualTo("123ABC")); 

    } 


    //The Builder class - Provides easy creation testdata. 
    internal class ObjectXBuilder 
    { 
     private MockRepository _mockRepository; 
     private IObjectX _objectX; 

     public ObjectXBuilder() 
     { 
      _mockRepository = new MockRepository(); 
      _objectX = _mockRepository.Stub<IObjectX>(); 
     } 

     public ObjectXBuilder WithName(string name) 
     { 
      _objectX.name = name; 
      return this; 
     } 

     public ObjectXBuilder WithId(long id) 
     { 
      _objectX.id = id; 
      return this; 
     } 

     public IObjectX Build() 
     { 
      _mockRepository.ReplayAll(); 
      return _objectX; 
     } 

    } 
Powiązane problemy