使用 rhino mocks 模拟没有接口的服务
Mock service without interfaces using rhino mocks
背景
我的应用程序正在通过代理使用 WCF 服务。我必须对我的实现进行单元测试,确保它使用服务并正确完成处理。
待测方法
public class MyClass
{
private ManagerServiceClientImpl myclient;
public void MethodToBeTested();
{
var result = GetServiceData();
if(result!=null)
//some processing
}
}
private MyObject GetServiceData()
{
myclient = ServiceLocator.Current.GetInstance<ManagerServiceClientImpl>();
if(myclient.ConnectToService() && myclient.MyServiceClient.IsConnected)
return myclient.GetData();
else
return null;
}
此为外源提供,本人无权修改
public class ManagerServiceClientImpl
{
public ServiceClient MyServiceClient { get; private set; }
public bool ConnectToService()
}
我如何模拟 ManagerServiceClientImpl
它没有接口或方法未标记为虚拟
到目前为止我尝试了什么。
[TestMethod]
public void IsServiceConnected_GetData()
{
//Arrange
ManagerServiceClientImpl clientImpl =
MockRepository.GenerateMock<ManagerServiceClientImpl>();
ServiceLocator.Expect(x => x.GetInstance<ManagerServiceClientImpl>())
.Return(clientImpl);
var testData= new MyObject
{
ID = "Test1",
Name ="test",
}
//Act
_myClass.MethodToBeTested();
//Assert
stubService.AssertWasCalled(h => h.SaveAllChanges());
}
注:使用Rhino.Mocks。这是我第一次使用 Rhino 模拟
为了使用 RhinoMocks(或 Moq,或任何其他 "constrained" 模拟框架),您正在模拟的类型必须支持对您要模拟的成员的继承。这意味着它必须是一个接口,或者成员必须是 virtual/abstract。否则,这些框架将无法执行它们在运行时生成代理中间人所需执行的操作。有关详细信息,请参阅我的博客 post,了解 .NET 模拟框架如何在幕后工作:https://www.wrightfully.com/how-net-mocking-frameworks-work
您可以做的是在您自己的 class 中创建方法来包装其他服务,这样您就可以模拟您的方法并拥有它们 return无论你需要什么,完全绕过服务。
正如 Amittai Shapira 提到的,您可以使用支持它的单元测试框架在没有接口的情况下模拟它,我正在使用 Typemock Isolator 并为您的代码创建了一个示例测试:
我已经创建了一个 MyClass 的实例,并使用 Typemock 的一个功能来模拟非 Public 方法来更改 GetServiceData
的 return 值
[TestMethod]
public void TestMethod1()
{
var testData = new MyObject
{
ID = "Test1",
Name = "test",
};
var realObj = new MyClass();
Isolate.NonPublic.WhenCalled(realObj, "GetServiceData").WillReturn(testData);
Isolate.NonPublic.WhenCalled(realObj, "SaveAllChanges").CallOriginal();
realObj.MethodToBeTested();
Isolate.Verify.NonPublic.WasCalled(realObj, "SaveAllChanges");
}
背景 我的应用程序正在通过代理使用 WCF 服务。我必须对我的实现进行单元测试,确保它使用服务并正确完成处理。
待测方法
public class MyClass
{
private ManagerServiceClientImpl myclient;
public void MethodToBeTested();
{
var result = GetServiceData();
if(result!=null)
//some processing
}
}
private MyObject GetServiceData()
{
myclient = ServiceLocator.Current.GetInstance<ManagerServiceClientImpl>();
if(myclient.ConnectToService() && myclient.MyServiceClient.IsConnected)
return myclient.GetData();
else
return null;
}
此为外源提供,本人无权修改
public class ManagerServiceClientImpl
{
public ServiceClient MyServiceClient { get; private set; }
public bool ConnectToService()
}
我如何模拟 ManagerServiceClientImpl
它没有接口或方法未标记为虚拟
到目前为止我尝试了什么。
[TestMethod]
public void IsServiceConnected_GetData()
{
//Arrange
ManagerServiceClientImpl clientImpl =
MockRepository.GenerateMock<ManagerServiceClientImpl>();
ServiceLocator.Expect(x => x.GetInstance<ManagerServiceClientImpl>())
.Return(clientImpl);
var testData= new MyObject
{
ID = "Test1",
Name ="test",
}
//Act
_myClass.MethodToBeTested();
//Assert
stubService.AssertWasCalled(h => h.SaveAllChanges());
}
注:使用Rhino.Mocks。这是我第一次使用 Rhino 模拟
为了使用 RhinoMocks(或 Moq,或任何其他 "constrained" 模拟框架),您正在模拟的类型必须支持对您要模拟的成员的继承。这意味着它必须是一个接口,或者成员必须是 virtual/abstract。否则,这些框架将无法执行它们在运行时生成代理中间人所需执行的操作。有关详细信息,请参阅我的博客 post,了解 .NET 模拟框架如何在幕后工作:https://www.wrightfully.com/how-net-mocking-frameworks-work
您可以做的是在您自己的 class 中创建方法来包装其他服务,这样您就可以模拟您的方法并拥有它们 return无论你需要什么,完全绕过服务。
正如 Amittai Shapira 提到的,您可以使用支持它的单元测试框架在没有接口的情况下模拟它,我正在使用 Typemock Isolator 并为您的代码创建了一个示例测试:
我已经创建了一个 MyClass 的实例,并使用 Typemock 的一个功能来模拟非 Public 方法来更改 GetServiceData
的 return 值[TestMethod]
public void TestMethod1()
{
var testData = new MyObject
{
ID = "Test1",
Name = "test",
};
var realObj = new MyClass();
Isolate.NonPublic.WhenCalled(realObj, "GetServiceData").WillReturn(testData);
Isolate.NonPublic.WhenCalled(realObj, "SaveAllChanges").CallOriginal();
realObj.MethodToBeTested();
Isolate.Verify.NonPublic.WasCalled(realObj, "SaveAllChanges");
}