简体   繁体   English

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

[英]C# Mock the object and expect its constructor to return mocked object using Rhino Mocks

I have an object which I initialize inside using block to dispose few things. 我有一个对象,该对象在内部使用block初始化以处理一些事情。 Then later inside using block I am calling some method of that object. 然后稍后在使用代码块的内部,我调用该对象的某些方法。

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

As I am writing unit test case for this, I have to mock the object and expect my own result by calling SomeMethod. 在为此编写单元测试用例时,我必须模拟对象并通过调用SomeMethod期望自己的结果。

I understand that If you want to mock any object then that object should be passed as a dependency and then we can expect our own result there but here in this case, if I pass the object as a dependency then I will not be able to use using block. 我知道,如果您要模拟任何对象,则应将该对象作为依赖项进行传递,然后我们可以在那里期待自己的结果,但是在这种情况下,如果我将对象作为依赖项进行传递,则将无法使用使用块。 For eg- 对于例如

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();
 }     
}

So my question is that 所以我的问题是

  1. Is there a way that I pass the mock object as a dependency and also use the object initialization but I should expect from my object that If your constructor is called anywhere in the code then please ignore that 有没有一种方法可以将模拟对象作为依赖项传递,也可以使用对象初始化,但是我应该从我的对象中期望,如果在代码中的任何地方调用了构造函数,请忽略该方法
  2. Shall I stop thinking of using Using block and call the dispose method manually 我是否应该停止考虑使用Using块并手动调用dispose方法

Thanks in advance 提前致谢

When adding the depency as parameter to your method, the client of that method isn´t only resposible for creating that depenency, but also for disposing it. 在将依赖关系作为参数添加到您的方法时,该方法的客户端不仅可用于创建该依赖关系,而且还可以用于处置它。 Thus there´s no need to have the using in your method. 因此您的方法中无需using However you´ll need it at the client-side: 但是,您将需要在客户端:

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

Now your method becomes something like this: 现在,您的方法将如下所示:

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

However when having a mock you surely won´t need to dipsoe it at all, at it is a leightweight instance whithout any unmanaged resources. 但是,当进行模拟时,您肯定根本不需要进行模拟,因为它是一个轻量级实例,没有任何不受管理的资源。

EDIT: If you are sure that MyMethod is the only place that uses the dependency, you can surely dispose it within that method as well: 编辑:如果您确定MyMethod是使用依赖项的唯一地方,则也可以肯定地将其置于该方法中:

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

However thais may lead to confusion to clients of MyMethod , as the dependecy will be disposed after calling this method: 但是Thais可能导致MyMethod客户感到困惑,因为在调用此方法后将处理依赖项:

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

There is a way to do this. 有一种方法可以做到这一点。 You want to pass dependency, but only for creation of the object. 您想传递依赖关系,但仅用于创建对象。 This way you can mock Dispose assuring you never dispose the object in tests. 这样,您就可以模拟Dispose确保您永远不会在测试中处理对象。 I don't have knowledge of rhino mock library, but you should get the idea. 我没有犀牛模拟库的知识,但是您应该明白这一点。

You need SomeClassFactory which will be dependency and will return an instance of SomeClass . 您需要SomeClassFactory ,它将是依赖项并返回SomeClass的实例。 This way you can mock SomeClass 's Dispose method and ignore disposing the object. 这样,您可以模拟SomeClassDispose方法,而忽略对对象的处理。

//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 is just a very simple factory SomeClassFactory只是一个非常简单的工厂

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

And put it all together: 放在一起:

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();
        }
    }
}

Please note this is only pseudo code. 请注意,这只是伪代码。 If you want any errors, please let me know. 如果您有任何错误,请告诉我。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM