使用犀牛嘲笑的模拟服务没有接口

时间:2017-04-28 09:13:41

标签: c# unit-testing wcf 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 mocks

2 个答案:

答案 0 :(得分:4)

正如Amittai Shapira所说,你可以使用支持它的单元测试框架在没有接口的情况下模拟它,我正在使用Typemock Isolator,我为你的代码创建了一个示例测试:

我创建了一个MyClass实例,并使用Typemock的一个功能来模拟非公共方法来更改GetServiceData的返回值

[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");
}

答案 1 :(得分:2)

为了使用RhinoMocks(或Moq,或任何其他“约束”模拟框架),您正在模拟的类型必须支持要模拟的成员的继承。这意味着它必须是一个接口,或者成员必须是虚拟/抽象的。没有它,这些框架就无法完成他们在运行时生成代理中间人所需要做的事情。有关更多详细信息,请参阅我的博客文章,了解.NET模拟框架如何在幕后工作:https://www.wrightfully.com/how-net-mocking-frameworks-work

可以做的是在你自己的类中创建包装其他服务的方法,这样你就可以模拟你的方法并让它们返回你需要的任何东西,完全绕过服务。