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

C# Moq:模拟具有多重继承的类,c#,moq,legacy-code,C#,Moq,Legacy Code,我正在对遗留代码进行一些测试(这里的意思是“没有单元测试的代码”)。有时会遵循良好的实践,但通常不会。不过,我还没有弄清楚在这种情况下需要做些什么 我需要能够在一个具体的类中测试我想要的方法,但一直无法,因为在我正在测试的类的构造函数中,它不仅具有我可以模拟的接口参数,而且还继承了另一个具有自己依赖项的基类 我要测试的方法是FilterController.SomeMethod(无论参数如何)。FilterController从BaseController继承。我还添加了一个简单的接口IFilt

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

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

我要测试的方法是FilterController.SomeMethod(无论参数如何)。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
    }
我当前用于尝试设置单元测试的代码(使用FluentAssertions和Moq的MSTest):

专用过滤器控制器过滤器控制器;
私有模拟过滤器控制器锁;
私人模拟食物堆;
私人模拟食物堆;
私人模拟食物堆;
私人模拟foo4mock;
[分类初始化]
公共静态void ClassInit(TestContext上下文){}
[测试初始化]
公共无效初始化()
{
filterControllerMock=newmock();
foo1mock=newmock();
foo2mock=newmock();
foo3mock=newmock();
foo4mock=newmock();
//这里是测试爆炸的地方,由于基类调用了未被模拟的东西,所以出现了异常
filterController=新的filterController(foo1mock.Object、foo2mock.Object、foo3mock.Object、foo4mock.Object);
}
[测试清理]
public void Cleanup(){}
[ExpectedException(typeof(CustomException))]
[测试方法]
public void SomeMethod_ForcedErrorScenario_catchescustomeException()
{
//安排
过滤器控制器锁
.Setup(x=>x.SomeMethod(It.IsAny(),It.IsAny())
.Returns(new CustomException());
//表演
var result=filterController.SomeMethod(“Foobar”,false);
}
在本例中,有一个Try-Catch块,我正在确保它在到达Catch块以确认bug已修复时得到正确处理。为了测试的目的,我不在乎异常是如何抛出的,只在乎它被捕获并完成我期望它完成的事情。但是,正如我所说的,由于它继承自BaseController,我无法通过模拟FilterController构造函数本身来调用其具体方法

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

发现了我的问题。。。在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=new filterController(interfacemock.Object)之前,我必须在[TestInitialize]初始化方法中这样做,我必须重写_IFoo1.AMethodNotMocked。像这样:

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

这使得当测试调用FilterController时,IFoo1接口被填充,这样就不会抛出空引用错误。

实际应用程序如何实例化
\u someOtherInterface
?它不是注射的。看来你需要重构它才能让它正常工作。我刚刚找到了那部分。它需要在构造函数中传递一个接口来调用和实例化另一个接口。我只需要在Initialize方法中添加一个调用来设置模拟接口,以覆盖它调用的方法。我将更新OP,但原始问题已解决。事实上,新版本与原始版本相差甚远,我宁愿为它创建一个全新的线程。很高兴听到你在进步,把答案写出来作为这个问题的答案,并打勾,这样可以帮助别人。
IFoo1.Setup(s => AMethodNotMocked()).Returns(new Foobar())