2016-08-04 88 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界面填充因此未抛出一个空引用错误。