Moq:模拟具有多重继承的类

本文关键字:多重继承 模拟 Moq | 更新日期: 2023-09-27 18:00:10

我正在对遗留代码进行一些测试(这里的意思是"没有单元测试的代码")。有时会遵循良好的做法,但往往不会。不过,我还没能弄清楚在这种情况下需要做什么。

我需要能够在一个具体的类中测试我想要的方法,但一直无法,因为在我测试的类的构造函数中,它不仅有我可以模拟的接口参数,而且还继承了另一个有自己依赖关系的基类。

我要测试的方法是FilterController.SomeMethod(whatever_params).FilterController继承自BaseController。我添加了一个简单的接口IFilterController,使FilterController继承了BaseController和IFilterCntroller。接口中唯一的方法是我想要测试的方法("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
    }

我目前尝试设置单元测试的代码(使用FluentAssessments和Moq的MSTest):

    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,我无法摆脱模拟FilterController构造函数本身来调用其具体方法的尝试。

--编辑:已解决问题。在BaseController中,_someOtherInterface是基于构造函数中传递的一个接口实例化的。在我的MSTest-Initialize方法中,我只需要使它成为一个null引用,然后用Setup(x=>x.otherMethod())覆盖它调用的方法。返回(_someOtherInterface.Object).

Moq:模拟具有多重继承的类

发现我的问题。。。在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]Initialize方法中这样做,然后它试图创建filterController=new filterController(interfacemock.Object)的东西,我必须重写_IFoo1.AMethodNotMocked

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

这使得当测试调用FilterController时,IFoo1接口被填充,因此不会引发null引用错误。