下面的using
会点击我不想实际点击的外部资源。我想测试someResult
以及使用它的代码,但每次运行单元测试时,此代码仍会尝试访问真正的Web服务。如何使用moq伪造对Web服务的真实调用,但不使用模拟其余代码?
public IMyInterface.SomeMethod()
{
// hits a web service
using ( mySoapClient client = new mySoapClient() )
{
var someResult = client.DoSomething();
...
...
}
}
[TestMethod()]
public void SomeMethodTest()
{
IMyInterface target = new MyInterface();
target.SomeMethod();
// Assert....
}
答案 0 :(得分:13)
您需要将Web服务实现与使用者
分离public class ClassIWantToTest
{
public ClassIWantToTest(IServiceIWantToCall service) {}
public void SomeMethod()
{
var results = service.DoSomething();
//Rest of the logic here
}
}
现在您可以使用Moq模拟IServiceIWantToCall
以测试SomeMethod
的逻辑
答案 1 :(得分:2)
要添加到pickles的答案,我为名为interface
的当前服务调用创建了IService
。然后我创建了一个继承接口的ServiceMock
类,并添加了一个名为_service
的全局变量。在构造函数中,我实例化模拟服务并设置接口的所有方法:
public class ServiceMock : IService
{
Mock<IService> _serviceMock;
public ServiceMock()
{
_serviceMock = new Mock<IService>();
_serviceMock.Setup(x => x.GetString()).Returns("Default String");
SomeClass someClass = new SomeClass();
someClass.Property1= "Default";
someClass.Property2= Guid.NewGuid().ToString();
_serviceMock.Setup(x => x.GetSomeClass()).Returns(someClass);
}
public string GetString()
{
return _serviceMock.Object.GetString();
}
public License GetSomeClass()
{
return _serviceMock.Object.GetSomeClass();
}
}
然后将此类注入代码而不是实际的Web服务。它将返回您设置的值以返回。您现在可以在不依赖于您的Web服务的情况下进行测试。
答案 2 :(得分:1)
首先必须能够注入Web服务。在SomeMethod()中创建一个新的方法将方法“紧密地”耦合到生产代码;你不能动态告诉它创建mySoapClient以外的东西。
由于您要创建和销毁它们,我可以建议您要测试的代码接受Func<IMySoapClient>
作为方法参数或构造函数参数。它看起来像这样:
public IMyInterface.SomeMethod(Func<IMySoapClient> clientFactory)
{
// hits a web service
using ( mySoapClient client = clientFactory() )
{
var someResult = client.DoSomething();
...
...
}
}
......或:
public class MyClass:IMyInterface
{
private Func<IMySoapClient> MySoapClientFactoryMethod;
public MyClass(Func<IMySoapClient> clientFactoryMethod)
{
MySoapClientFactoryMethod = clientFactoryMethod;
}
...
public IMyInterface.SomeMethod()
{
// hits a web service
using ( mySoapClient client = MySoapClientFactoryMethod() )
{
var someResult = client.DoSomething();
...
...
}
}
}
现在,当您创建要测试的对象时,您可以定义一个函数,该函数生成Soap服务的相应Moq模拟,它具有您期望从真实客户端获得的行为而没有副作用(包括能够告诉客户端的代码Dispose()d,并将该函数传递给您正在测试的类或方法。在生产中,您可以简单地将函数定义为()=>new mySoapClient()
,或者您可以设置IoC框架并将mySoapClient注册为IMySoapClient,然后注册MyClass;大多数IoC框架足够聪明,可以将委托视为参数,并生成注入已注册依赖项的方法。