Nie wiem co to jest pole wew. metody
ale też nie programuje w .net więc to może dlatego.
Przykład będzie w javie, ale postaram się żeby był dość jasny. Mamy sobie klasę:
class SumOddNumbers{
@Inject
private ParityChecker parityChecker;
@Inject
private Summator summator;
public int sum(List<Integer> input){
summator.clear();
Iterator<Integer> it = input.iterator();
while(it.hasNext()){
Integer number = it.next();
if (parityChecker.isOdd(number)){
summator.add(number);
}
}
return summator.getSum();
}
}
I chcemy ten kod przetestować nie zaprzęgając do tego ani Summatora ani ParityCheckera. est mógłby wyglądać na przykład tak:
@Test
public void testAddOddNumbers(){
SumOddNumbers sumOddNumbers = new SumOddNumbers();
List<Integer> input = Arrays.asList(1,2,3,4);
expect(parityChecker.isOdd(anyInt()).andReturn(true).anyTimes();
summator.clear();
expectLastCall().atLeastOnce();
for(int element : input){
summator.add(element);
expectLastCall().once();
}
int expectedResult = 10;
expect(summator.getSum()).andReturn(expectedResult).atLeastOnce();
replayAll();
int result = sumOddNumbers.sum(input);
verifyAll();
assertEquals(expectedResult, result);
}
Test jest ustawiony tak, że uzna każdą liczbę za nieparzystą. Nasze oczekiwania wobec testu są takie, że sumator zostanie wyzerowany, następnie każdy element wejścia zostanie dodany raz, a wynikiem działania metody będzie suma zwrócona przez sumator.
Jak mógłby wyglądać źle napisany test? Na przykład tak:
@Test
public void testAddOddNumbers(){
SumOddNumbers sumOddNumbers = new SumOddNumbers();
List<Integer> input = createMock(List.class);
Iterator<Integer> iterator = createMock(Iterator.class);
expect(input.iterator()).andReturn(iterator).once(); // oczekujemy że ktoś zawoła iterator i weźmie go raz, bo tak jest w kodzie
int elementsInInput = 4;
expect(iterator.hasNext()).andReturn(true).times(elementsInInput); // oczekujemy że ktoś raz przeleci iteratorem całe wejście
expect(iterator.next()).andReturn(0).times(elementsInInput);
expect(parityChecker.isOdd(anyInt()).andReturn(true).times(elementsInInput); // oczekujemy że parzystość dla każdej liczby zostanie sprawdzona tylko raz, bo tak jest w aktualnej implementacji
summator.clear();
expectLastCall().once(); // oczekujemy że sumator zerowany będzie tylko raz, bo tak jest w aktualnej implementacji
for(int element : input){
summator.add(element);
expectLastCall().once();
}
int expectedResult = 10;
expect(summator.getSum()).andReturn(expectedResult).once();
replayAll();
int result = sumOddNumbers.sum(input);
verifyAll();
assertEquals(expectedResult, result);
}
Widzisz co z tym testem jest nie tak? Co się stanie jeśli zamienie sobie tą pętlę w kodzie np. na pętlę
for(int i=0;i<input.size();i++){
Integer number = input.get(i);
//itd
}
? Test sie wysypie, mimo że kod działa poprawnie.
Albo co będzie jeśli dodam sobie w kodzie logowanie i będzie np.
if (parityChecker.isOdd(number)){
logger.log("Parity check = "+parityChecker.isOdd(number));
summator.add(number);
}
Znów test się sypnie ;]
Edit: moim zdaniem ten "test" który pokazałeś niczego nie testuje. Masz tam 3 asercje z czego dwie pierwsze są bez sensu bo nijak nie testują twojego kodu a trzecia sprawdza za mało żeby mieć jakiekolwiek znaczenie. Przecież ja mógłbym teraz wziąć tą twoją metodę, wywalić całe jej ciało, utworzyć pusty EditDriverModel
, przypisać mu do cars
ala ma kota a sierotka ma rysia
a twój test nadal by twierdził że wszystko jest ok :D
Edit2:
Ja tu widze miejsce na przynajmniej kilka osobnych testów. Jeden test na ten wyjątek, tzn mockujesz rzucenie wyjątku i sprawdzasz czy metoda zachowa sie tak jak powinna. Poza tym ten kawałek z tworzeniem EditDriverModel można wydzielić do osobnej metody i napisać test który sprawdzi czy poprawnie przepisujesz dane z miejsce na miejsce. Test tej głównej metody jak dla mnie powinien zawierać:
- weryfikacje czy pobraliśmy z bazy odpowiedniego drivera
- weryfikacje czy do utworzenia EditDriverModel przekazaliśmy ten pobrany obiekt
Dodatkowo możemy zrobić:
- weryfikacje czy pobraliśmy z bazy listę samochodów
- weryfikacje czy utworzyliśmy selection list z listy samochodów
- weryfikacje czy lista samochodów została zwrócona w modelu