2016-08-04 37 views
2

我正在對遺留代碼(這裏是指「沒有單元測試的代碼」)進行一些測試。有時會遵循好的做法,但通常不會。儘管如此,我還是無法弄清楚在這種情況下需要做些什麼。Moq:嘲笑一個具有多重繼承的類

我需要能夠在具體的類中測試我想要的方法,但一直不能,因爲在我測試的類的構造函數中,它不僅具有我可以模擬的接口參數,而且它也從另一個具有自己的依賴關係的基類繼承。

我想測試的方法是FilterController.SomeMethod(whatever_params)。 FilterController繼承自BaseController。我已經添加了一個簡單的IFilterController接口,使FilterController繼承了BaseController和IFilterController。我在界面中唯一的方法是我想測試的方法(「SomeMethod」)。

現在,FilterController的構造函數就是我在跳轉到BaseController時遇到的問題。

public interface IFilterController { ActionResult SomeMethod(string s, bool b) } 

public class FilterController : BaseController, IFilterController { 
    public FilterController(IFoo1 foo1, IFoo2 foo2, IFoo3 foo3, IFoo4 foo4) 
     : base(typeof(FilterController), foo1, foo2, foo3, foo4) {} 
    public ActionResult SomeMethod(string s, bool b) { // implementation } 


// and the BaseController... 
public BaseController(Type type, IFoo1 foo1, IFoo2 foo2, IFoo3 foo3, IFoo4 foo4) 
    { 
     // call that blows up due to not knowing how to mock the call inside here 
     _somePrivateProperty = _someOtherInterface.someCallThatIsntMocked(some_params) 
     // other stuff 
    } 

我現在有想安裝的單元測試(MSTest的具有FluentAssertions和MOQ)代碼:

private FilterController filterController; 
    private Mock<IFilterController> filterControllerMock; 
    private Mock<IFoo1> foo1mock; 
    private Mock<IFoo2> foo2mock; 
    private Mock<IFoo3> foo3mock; 
    private Mock<IFoo4> foo4mock; 

    [ClassInitialize] 
    public static void ClassInit(TestContext context) {} 

    [TestInitialize] 
    public void Initialize() 
    { 
     filterControllerMock = new Mock<IFilterController>(); 
     foo1mock = new Mock<IFoo1>(); 
     foo2mock = new Mock<IFoo2>(); 
     foo3mock = new Mock<IFoo3>(); 
     foo4mock = new Mock<IFoo4>(); 

     // here is where the test bombs out with exceptions due to the base class making calls to stuff not mocked 
     filterController = new FilterController(foo1mock.Object, foo2mock.Object, foo3mock.Object, foo4mock.Object); 
    } 

    [TestCleanup] 
    public void Cleanup(){} 

    [ExpectedException(typeof(CustomException))] 
    [TestMethod] 
    public void SomeMethod_ForcedErrorScenario_CatchesCustomException() 
    { 
     // Arrange 
     filterControllerMock 
      .Setup(x => x.SomeMethod(It.IsAny<string>(), It.IsAny<bool>())) 
      .Returns(new CustomException()); 

     // Act 
     var result = filterController.SomeMethod("Foobar", false);   
    } 

在這種情況下,是我確保被處理的try catch塊當它到達catch塊以確認錯誤得到修復時,應該正確。我不在乎爲了測試的目的而拋出異常,只是它被捕獲並且做了我期望的事情。然而,正如我所說的,我不能過去試圖模擬FilterController構造函數本身來調用其具體方法,因爲它繼承了BaseController。

- 編輯:解決了這個問題。在BaseController中,_someOtherInterface是基於在構造函數中傳遞的接口之一實例化的。在我的MSTest Initialize方法中,我只需要讓接口不會是空引用,然後使用安裝程序(x => x.otherMethod())覆蓋它調用的方法。返回(_someOtherInterface.Object)。

+1

真正的應用程序如何實例化_someOtherInterface?它沒有被注入。看起來你需要重構它才能正常工作。 – Jonesopolis

+0

我只是想出了那部分。它需要構造函數中傳遞的接口之一來調出並實例化其他接口。我只需在Initialize方法中添加一個調用來設置該模擬接口來覆蓋它所調用的方法。我會更新OP,但原來的問題已解決。實際上,這個新問題與原始問題相去甚遠,我寧願爲它創建一個新線程。我會解開它一段時間,看看我是否可以自己先弄明白。 – user1709953

+0

很高興聽到您正在取得進展 – Jonesopolis

回答

1

發現我的問題......在BaseController

// I didn't realize the _someOtherInterface was instantiated based off an interface passed in 
_someOtherInterface = _IFoo1.AMethodNotMocked(); 
// many lines later... 
_somePrivateProperty = _someOtherInterface.SomeMockedMethod() 

要解決,我不得不然後使它所以在[TestInitialize]初始化方法的問題之前,它試圖創建filterController =新FilterController(interfacemock .Object)的東西,我不得不重寫_IFoo1.AMethodNotMocked。像這樣:

IFoo1.Setup(s => AMethodNotMocked()).Returns(new Foobar()) 

這使得它所以當被叫進FilterController測試中,IFoo1界面填充因此未拋出一個空引用錯誤。