C#模拟对象并期望其构造函数使用Rhino Mocks返回模拟对象

时间:2018-01-25 08:55:58

标签: c# unit-testing rhino-mocks

我有一个对象,我使用块初始化内部处理一些东西。然后在内部使用块我调用该对象的一些方法。

public void MyMethod()
{
 using(var obj = new Someclass())
 {
   // I want to mock this method call
   var result = obj.SomeMethod();
 }
}   

当我为此编写单元测试用例时,我必须通过调用SomeMethod来模拟对象并期望我自己的结果。

我理解如果你想模拟任何对象,那么该对象应该作为依赖项传递,然后我们可以期待我们自己的结果,但在这种情况下,如果我将对象作为依赖项传递,那么我将不会能够使用块。例如 -

public void MyMethod(SomeClass object)
{
 // Here can I do something like this ?
 // If this works then I can easily send the mocked object
 using(var obj = object)
 {
   // I want to mock this method call
   var result = obj.SomeMethod();
 }     
}

所以我的问题是

  1. 有没有一种方法可以将模拟对象作为依赖项传递,也可以使用对象初始化,但我应该从我的对象中得到如果你的构造函数在代码中的任何地方被调用,那么请忽略它
  2. 我不想再使用Using block并手动调用dispose方法
  3. 提前致谢

2 个答案:

答案 0 :(得分:0)

将依赖项作为参数添加到您的方法时,该方法的客户端不仅可以为创建该依赖性,而且还可以处理它。因此,无需在方法中使用using 。但是你需要在客户端:

using(var mock = Mock<MyClass>()) // don´t know the exact Rhino-syntax to get a mock
{
    MyMethod(mock);
}

现在你的方法就像这样:

void MyMethod(MyClass m)
{
    m.SomeMethod();  // notice that there´s no using
}

然而,当有一个模拟器时,你肯定不需要对它进行dipsoe,它是一个轻量级的实例,没有任何非托管资源。

编辑:如果你确定MyMethod是唯一使用依赖项的地方,你肯定也可以在该方法中处理它:

void MyMethod(MyClass m)
{
    using(m) { m.SomeMethod(); }
}

然而,thais可能会导致MyMethod的客户混淆,因为在调用此方法后将依赖该处理:

var m = Mock<MyClass>();
MyMethod(m);
m.DoSomething();  // will lead to ObjectDisposedException

答案 1 :(得分:0)

有一种方法可以做到这一点。您希望传递依赖关系,但仅用于创建对象。这样你就可以模拟Dispose,确保你永远不会在测试中处理对象。我不了解犀牛模拟库,但你应该明白这一点。

您需要SomeClassFactory这将是依赖项,并将返回SomeClass的实例。这样您就可以模拟SomeClass Dispose方法并忽略处理对象。

//Arrange
var someClassFactoryMock = MockRepository.GenerateMock<ISomeClassFactory>();
var someClassMock = MockRepository.GenerateMock<ISomeClass>();
someClassMock.Stub(s => s.Dispose()); // Ignore Dispose
someClassFactoryMock.Stub(s => s.Get()).Return(someClassMock); // Return mock
var fooClass = new Foo();
fooClass.SomeClassFactory = someClassFactoryMock;

// Act
fooClass.SomeMethod();

// Assert
someClassMock.Expect(s => s.SomeMethod()).Repeat.Times(1); // Assert that it was called once.

SomeClassFactory只是一个非常简单的工厂

public class SomeClassFactory : ISomeClassFactory
{
    public ISomeClass Get() => new SomeClass();
}

并将它们放在一起:

public class Foo
{
    public ISomeClassFactory SomeClassFactory { get; set; }
    public void MyMethod()
    {
        using(ISomeClass obj = SomeClassFactory.Get())
        {
          // When testing, obj will be a mock with Dispose method mocked to not do anything. This way it will not be disposed.
           var result = obj.SomeMethod();
        }
    }
}

请注意这只是伪代码。如果您有任何错误,请告诉我。