【问题标题】:Mock service without interfaces using rhino mocks使用 rhino 模拟没有接口的模拟服务
【发布时间】:2017-04-28 09:13:40
【问题描述】:

背景 我的应用程序正在通过代理使用 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 模拟

【问题讨论】:

  • 将第 3 方依赖项包装在您在代码中控制的抽象中,并且能够修改和模拟。避免服务定位器反模式,这会使代码难以测试,正如您已经发现的那样。这是一个设计问题。
  • 你能举个例子吗
  • 首先您需要澄清要测试的方法,因为您的示例不清楚。
  • 我没有完全理解你MethodToBeTested(); 是要测试的。该方法中的逻辑非常小。如果服务数据不在清单中,则添加到清单中。我不确定这是你要求的。请原谅我的英语`
  • 检查你的小例子,看看它是否能编译。这不是minimal reproducible example。到目前为止,您尝试过的代码还引用了在被测方法中甚至没有指明的方法。你明白我的意思吧?

标签: c# unit-testing wcf rhino-mocks


【解决方案1】:

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

我创建了一个 MyClass 的实例,并使用 Typemock 的一个特性来模拟 Non-Public 方法来更改 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");
}

【讨论】:

  • 我无权将typemock 添加到我们的项目中。我现在仅限于使用 rhino mock。感谢您的支持。
【解决方案2】:

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

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

【讨论】:

  • 在下面列出的文章中,您可以看到可以使用 Telerik JustMock、Typemock Isolator 和 Microsoft Fakes 等“无约束框架”模拟非虚拟 3rd 方库。
猜你喜欢
  • 1970-01-01
  • 2010-12-03
  • 1970-01-01
  • 2011-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多