2011-10-21 21 views
7

Obecnie prowadzone testy, które wyglądać następująco:Jak korzystać MOQ przetestować kod, który wywołuje chronionych pomocników

// In Blah.cs 
public class ClassUnderTest 

{ 

    public bool MethodUnderTest() 

    { 

     // Do a bunch of stuff... 

     return HelperMethod(); 

    } 



    protected virtual bool HelperMethod() 

    { 

     bool success = false; 

     // Proprietary Hardware Access. 

     // Database Calls. 

     // File System Modifications. 

     return success; 

    } 

} 


// In TestBlah.cs 

public class TestStub : ClassUnderTest 

{ 

    public bool HelperMethodReturnValue; 



    protected override bool HelperMethod() 

    { 

     return HelperMethodReturnValue; 

    } 

} 



[TestClass] 

public class TestingClass 

{ 

    [TestMethod] 

    public void ClassUnderTest_MethodUnderTest_TestHelperReturnsTrue() 

    { 

     var stub = new TestStub(); 

     stub.HelperMethodReturnValue = true; 

     Assert.IsTrue(stub.MethodUnderTest()); 

    } 



    [TestMethod] 

    public void ClassUnderTest_MethodUnderTest_TestHelperReturnsFalse() 

    { 

     var stub = new TestStub(); 

     stub.HelperMethodReturnValue = false; 

     Assert.IsFalse(stub.MethodUnderTest()); 

    } 

} 

Powyższy wygląda dobrze dla prostych rzeczy, jednak klasa en dostaje wykładniczo większy i bardziej skomplikowany szybko . Chciałbym zastąpić klasę pośrednią za pomocą Moq. Jednak to się nie skompiluje, ponieważ z jakiegoś powodu nie mogę ustawić wartości zwracanej na chronionej metodzie.

[TestMethod] 

public void ClassUnderTest_MethodUnderTest_TestHelperReturnsFalse() 

{ 

    var mockClass = new Mock<ClassUnderTest>(); 
    mockClass.Protected().Setup("HelperMethod").Returns(false); 

    Assert.IsFalse(mockClass.Object.MethodUnderTest()); 

} 

Ktoś wie, jak to zrobię? Czy mogę to zrobić z moq?

+5

Coś tu nie wygląda ... nie kpisz z SUT, kpisz z jego zależności. –

+0

Tak, faktycznie Yojin kpi z SUT, aby zastąpić część SUT, która powinna być przechowywana osobno, a nie w chronionej metodzie pomocniczej. – Matthias

Odpowiedz

23

Patrząc na moq source code ja bym przypuszczenie trzeba jawnie wywołać ogólną wersję Instalatora. Wersja nietypowa wydaje się być używana do nieważnych metod. Więc spróbuj

Oprócz tego, polecam ponowne przemyślenie swojego projektu klasy. Jeśli HelperMethod() robi taką masę rzeczy, byłoby warte swojej własnej klasy, która jest wstrzykiwana jako zależność do ClassUnderTest. Testowanie fałszywego obiektu, zamiast użycia fałszywego obiektu, aby przetestować coś "prawdziwego", nie jest tym, za co szykowane są ramy (nie w pierwszej kolejności).

4

Metody chronione nie są doskonałym sposobem izolowania zależności, ale czasami pojawiają się, szczególnie w przypadku dostosowywania starszego kodu do testowalności. Jedną z opcji, która pozwala uniknąć nieporęcznej składni opartej na Moq, jest uczynienie metody "wewnętrzną chronioną" (lub po prostu "wewnętrzną", jeśli nie zamierzasz jej zastąpić w normalnym użytkowaniu z innych złożeń.) Następnie używasz elementu InternalsVisibleTo w zespole ujawnić metodę. To trochę hack, ale używanie w tym celu metody chronionej jest już trochę hackerem. Pod pewnymi względami preferuję podejście "wewnętrzne", ponieważ daje to do zrozumienia, że ​​jest to metoda backdoora, której nie należy używać (z wyjątkiem testów), w przeciwieństwie do metody chronionej, której można się spodziewać w normalnym trybie stosowanie.

Powiązane problemy