简体   繁体   中英

Mock an instance inside a class in C#

I'm trying to mock an instance inside a class. This is the class(simplified):

public void CreatePhotos(string elementType) 
{ 
    var foo = new PicturesCreation(); 

    //some code here...

    if (elementType == "IO") 
    { 
        foo.CreateIcons(client, new PicturesOfFrogsCreation(), periodFrom, periodTo)
    } 
}

So I'm trying to mock this 'new PicturesOfFrogsCreation()' for a Unit test, to see if CreateIcons is called with this parameter. I tried to use Rhino Mocks/ AssertWasCalled method to achieve this in my test, but it looks it's not working, since I just know how to mock interfaces. Do you know if it is possible to mock this?

Update: The code of the PicturesCreation class:

internal sealed class PicturesCreation 
    { 
      public void CreateIcons(IPictures foo, int periodFrom, int periodTo) 

         { 
            foo.CreateIcons(periodFrom, periodTo); 
         } 
    }

And the code of PicturesOfFrogsCreation:

internal sealed class PicturesOfFrogsCreation : IPictures
{ 

    public void CreateIcons(int periodFrom, int periodTo) 
      { 
         //Code that implements the method
      } 
}

I wrote this test, but I'm not sure if it's well written:

public void Create_commitment_transaction_should_be_called_for_internal_order() 
    { 

       IPicture fooStub = RhinoStubWrapper<IPicture>.CreateStubObject(); 

       rebuildCommitmentsStub.StubMethod(x => x.CreateIcons(Arg<int>.Is.Anything, Arg<int>.Is.Anything));

       PicturesProcess.CreatePhotos("IO"); 

       rebuildCommitmentsStub.AssertWasCalled(x => x.CreateIcons(Arg<int>.Is.Anything,Arg<int>.Is.Anything));

    }

Thanks in advance!

A.

Your code doesn't seem to be designed for this to be honest. Because you are instantiating the instance within your method, and then calling the method, it's hard to mock it out.

If you passed the instance in, either to this method, or to the class's constructor to be captured in a field, then it could be replaced with a mock - most mocking frameworks (including Rhino) can do this, provided the method you are checking is virtual.


Edit: I see from your edit that the classes in question are sealed. This makes them essentially unmockable. Mocking a class works by creating a proxy class that inherits from the class being mocked - if it's sealed, this can't be done.

You need to inject dependencies that you wish to mock on. Local variables are private to the methods and cannot be asserted upon. An example -

public class Photo{
  private IPicturesCreation foo;
  public test(IPicturesCreation picturesCreation)
  {
    foo = picturesCreation;
  }

  public void CreatePhotos(string elementType) 
    { 
    //some code here...

    if (elementType == "IO") 
       { 
           foo.CreateIcons(client, new PicturesOfFrogsCreation(), periodFrom, periodTo)
       } 
    }
}

And Test it like this

public class PhotoTest{
    public testFunctionCall(){
    var mockPicturesCreation = new Mock<IPicturesCreation>();
    new Photo(mockPicturesCreation.Object).CreatePhotos("blah");
    mockPicturesCreation.Verify(x => x.CreateIcons(.....), Times.Once);
    }
}

As others already mentioned, this code is not very suited for mocking. However, if you can't modify the code, there are still some options though.

I heard that TypeMock can mock sealed classes, but I've never worked with it. It's commercial software btw... And there's the Microsoft Fakes Framework (Comes with VS Premium). I played with it a bit, and it seems you can test virtually anthing. Definitely worth checking out!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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