2013-07-12 14 views
6

Mam metodę, której operacje zależą od jej podopiecznych, jak poniżej. Czy nadal warto wykonywać test jednostkowy? Ponieważ test jednostkowy nie testuje żadnej logiki biznesowej, a raczej przez mocks.Czy test jednostki może wykonywać podwójne obciążanie, akceptując wartość logiczną jako przełącznik, czy też powinienem napisać dwa oddzielne testy, które powielają kod testowy?

testów jednostkowych poniżej:

Uwaga opetions metoda jest określana przez expectedCustomerValidality, który jest ustawiony w teście. Głównie, logika jest określana przez mocks (np Setup(c => c.IsValid())

 [Test] 
     [TestCase(true)] 
     [TestCase(false)] 
     public void AddCustomer(bool expectedCustomerValidality) 
     { 
      //using Moq 
      companyRepositoryMock.Setup(c => c.GetById(It.IsAny<int>())).Returns(new Company());   
      customerValidatorMock.Setup(c => c.IsValid(It.IsAny<Customer>())).Returns(expectedCustomerValidality); 

      var customer = new Customer 
           { 
            Firstname = "firstName", 
            Surname = "surname", 
            Company = new Company { Id = 1 } 
           }; 

      var addCustomer = customerServiceSut.AddCustomer(customer); 

      Assert.AreEqual(expectedCustomerValidality,addCustomer); 
     } 

kod Produkcja poniżej.

public class CustomerService : ICustomerService 
    { 
     private ICompanyRepository companyRepository; 
     private ICustomerRepository customerRepository; 
     private ICustomerValidator customerValidator; 

     public CustomerService(ICompanyRepository companyRepository, ICustomerRepository customerRepository, ICustomerValidator customerValidator) 
     { 
      this.companyRepository = companyRepository; 
      this.customerRepository = customerRepository; 
      this.customerValidator = customerValidator; 

     } 

     public bool AddCustomer(Customer customer) 
     {   
      customer.Company = companyRepository.GetById(customer.Company.Id); ; 

      if (customerValidator.IsValid(customer)) 
      { 
       customerRepository.AddCustomer(customer); 

       return true; 
      } 

      return false; 
     } 
} 

pytania:

  • Czy AddCustomer() wymagana jednostka testowanie
  • Jeśli tak, czy aktualny test jednostki działa prawidłowo?

    1 Jeśli nie, jaki jest właściwy sposób testowania urządzenia?

+0

1. Wszystkie metody zawierające nietrywialną logikę powinny być testowane w jednostce. 2. Co rozumiesz przez "poprawny?" –

+0

1. Masz na myśli, że AddCustomer zawiera nietrywialną logikę. Ale to zależy od zależności, która jest wyśmiewana. 2. W teście, jeśli gałąź jest określona przez fałszywy obiekt. – Pingpong

Odpowiedz

7

Nie podoba mi się to. Oto dlaczego: imiona wasze metody badania powinna odzwierciedlać sposób w ramach testu, jakie warunki testu są i czego można oczekiwać na wynik testu będzie:

public bool AddCustomer_CustomerIsValid_ShouldReturnTrue() 

public bool AddCustomer_CustomerIsInvalid_ShouldReturnFalse() 

Teraz, jeśli chcesz, możesz byłaby podstawowa logika testowania do własnej metody eliminacji duplikacji kodu, a następnie wywołanie tej metody z dwóch powyższych metod. Ale metoda refaktoryzacji nie jest przypadkiem testowym; to tylko pomocna metoda dla rzeczywistych przypadków testowych.

Przykład:

[Test] 
public void AddCustomer_CustomerIsValid_ShouldReturnTrue() 
{ 
    var result = AddCustomerTest(true); 
    Assert.IsTrue(result); 
} 

[Test] 
public void AddCustomer_CustomerIsInvalid_ShouldReturnFalse() 
{ 
    var result = AddCustomerTest(false); 
    Assert.IsFalse(result); 
} 

public void AddCustomerTest(bool expectedCustomerValidality) 
{ 
    //using Moq 
    companyRepositoryMock.Setup(c => c.GetById(It.IsAny<int>())).Returns(new Company());   
    customerValidatorMock.Setup(c => c.IsValid(It.IsAny<Customer>())).Returns(expectedCustomerValidality); 

    var customer = new Customer 
    { 
     Firstname = "firstName", 
     Surname = "surname", 
     Company = new Company { Id = 1 } 
    }; 

    var result= customerServiceSut.AddCustomer(customer); 

    return result; 
} 
+1

+1 .. testy jednostkowe nie są wyłączone z refaktoryzacji/czyszczenia. –

+0

Czy mógłbyś to wyjaśnić, na przykład? – Pingpong

+0

@Pingpong: Twój 'AddCustomer (bool expectedCustomerValidality)' nie jest już metodą testową. Zamiast tego jest to metoda refaktoryzowana, którą wywołują powyższe dwie metody testowania. Zwróć wartość logiczną w metodzie refaktoryzowanej i upewnij się, że zwracana wartość jest poprawna w każdej z dwóch metod testowania.Zobacz moją zaktualizowaną odpowiedź. –

0

AddCustomer wymaga badań, gdyż wykonuje logikę biznesową - pobiera firmę i ustawia go, to sprawdza dane, dodaje dane do repozytorium, i zwraca wynik.

Twój test jest prawie poprawny. Chciałbym zrobić to trochę bardziej szczegółowy, aby zweryfikować całą logikę biznesową:

[Test] 
[TestCase(true)] 
[TestCase(false)] 
public void AddCustomer(bool isCustomerValid) 
{ 
    //arrange 
    //NOTE!!! create the mocks with MockBehavior.Strict 
    //that way the test will fail if a call is made w/o setup 

    const long testCompanyId = 100; 
    var testCompany = new Company{ Id = testCompanyId }; 
    companyRepository.Setup(r => r.GetById(testCompanyId)) 
      .Returns(testCompany); 

    var testCustomer = new Customer 
        { 
         Firstname = "firstName", 
         Surname = "surname", 
         Company = new Company { Id = testCompanyId } 
        }; 

    customerValidatorMock.Setup(c => c.IsValid(It.Is<Customer>(c => c == testCustomer && c.Company == testCompany)).Returns(isCustomerValid); 

    if (isCustomerValid) 
    { 
      customerRepository.Setup(r => r.AddCustomer(testCustomer)). Verifiable(); 
    } 

    //act   
    var addCustomerResult = customerServiceSut.AddCustomer(testCustomer); 

    //assert 
    Assert.AreEqual(isCustomerValid, addCustomerResult); 
    cutomerRepository.VerifyAll(); 
} 

Powyższy test przetestować wszystkie funkcje metody usługi, w tym, czy firma jest osiągane przez id, a jeśli naciągane jeden jest używany. Sprawdza również, czy klient jest dodany, jeśli jest ważny. Test zakończy się niepowodzeniem, jeśli klient zostanie dodany, jeśli nie będzie prawidłowy (ponieważ element customerRepository został utworzony za pomocą MockBehavior.Strict, a konfiguracja nie zostanie wykonana).