2017-06-01 50 views
2

我试图模拟一个从SoapHttpClientProtocol继承的web服务对象,并且我无法在我的单元测试中进行修改。不幸的是,当我尝试:使用NSubstitute嘲弄webservice错误

var myApi = Substitute.ForPartsOf<MyAPIClass>(); 

我得到以下错误:

Message: Test method MyProj.Test.Business.Folder.CalendarEventServiceUnitTest.GetPerformances_WithEventsAndPerformances_CorrectlyDistinguishesThem threw exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidOperationException: There was an error reflecting type 'MyNamespace.MyAPIClass'. ---> System.InvalidOperationException: Cannot serialize member 'System.ComponentModel.Component.Site' of type 'System.ComponentModel.ISite', see inner exception for more details. ---> System.NotSupportedException: Cannot serialize member System.ComponentModel.Component.Site of type System.ComponentModel.ISite because it is an interface.

+0

不要试图模拟你无法控制的代码(第三方代码)。抽象出所需的行为,并在抽象的实现中封装第三方代码。 – Nkosi

+0

@Nkosi这个API是我测试的依赖项。我所要做的就是当有人在API上调用MyMethod()时,返回一个假数据集,所以我实际上并没有在单元测试中调用服务。这不是一个应该被嘲讽框架支持的用例吗? – khalid13

+0

不是你想要嘲笑的是不可嘲笑的,这是因为你无法修改它。 – Nkosi

回答

2

不要尝试模拟代码,你没有控制权(即第三方代码)。在您的抽象实现中抽象出期望的行为并封装第三方代码。

public interface IMyApiInterface { 
    //...code removed for brevity 
} 

将抽象注入到它们的依赖类中。这将允许您的单元测试更好地嘲笑,并且整体上具有更灵活/可维护的架构。

var myApi = Substitute.For<IMyApiInterface>(); 

该接口的实际实现将封装或组成实际的Web服务。

public class MyProductionAPIClass : MyAPIClass, IMyApiInterface { 
    //...code removed for brevity 
} 

不要将代码紧密地结合到不允许灵活且可维护的代码的实现问题上。取决于抽象。

+0

我最终遵循了你的方法。谢谢。 – khalid13