Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to moq a static class with a static method (UnitOfWork case)?

Tags:

c#

.net

mocking

moq

I have these classes:

public static class UnitOfWorkSS 
{
  public static IUnitOfWork Begin()
  {
    return IoC.Resolve<IUnitOfWork>();
  }
}

public class PostService
{
  using (IUnitOfWork unitOfWork = UnitOfWorkSS.Begin())
  {
    //don't forget to sanitize html content
    htmlContent = _htmlSanitizer.Sanitize(htmlContent);

    IPost post = _factory.CreatePost(byUser, title, htmlContent);                    

    _postRepository.Add(post);

    unitOfWork.Commit();
  }
}

How can I mock the classes UnitOfWorkSS and unitOfWork?

like image 804
Attilah Avatar asked Nov 26 '10 03:11

Attilah


People also ask

Can you MOQ a static class?

Mocking Static MethodsFree tools like Moq can only mock interfaces or virtual/abstract methods on classes with a public default constructor. If you need to truly mock static methods, you need to use a commercial tool like Microsoft Fakes (part of Visual Studio Enterprise) or Typemock Isolator.

Can we mock static methods using MOQ?

You can use Moq to mock non-static methods but it cannot be used to mock static methods. Although static methods cannot be mocked easily, there are a few ways to mock static methods. You can take advantage of the Moles or Fakes framework from Microsoft to mock static method calls.

How do you write a test case for a static method?

Note that you should add the class that contains static methods in two places in your unit tests: On top of the unit test class using @PrepareForTest annotation. In your test setup by calling the PowerMockito. mockStatic to do the necessary initialization step before trying to mock any of its methods.

How do you mock static class in NSubstitute?

NSubstitute can't mock static methods, so if you want to use NSub for this you'll need to rewrite the original class, or wrap the functionality in a new class that you can mock.


2 Answers

It looks like the only thing you are doing with the call to Begin() is returning your configured class for that particular interface: IUnitOfWork

You really just need to make sure that your call to Begin() returns a mock implementation of IUnitOfWork

One of two ways you can do this:

Option One - Refactor UnitOfWorkSS so that you can set the instance of IUnitOfWork to be returned

public static class UnitOfWorkSS  
{
    private static IUnitOfWork _unitOfWork;
    public static IUnitOfWork UnitOfWork
    {
        set { _unitOfWork = value; }
        private get{ _unitOfWork ?? (_unitOfWork = IoC.Resolve<IUnitOfWork>()); }
    }

    public static IUnitOfWork Begin()  
    {  
        return UnitOfWork;
    }  
}  

[TestMethod]
public void DoStuff()
{
    var mockUnitOfWork = new Mock<IUnitOfWork>();
    UnitOfWorkSS.UnitOfWork = mockUnitOfWork.Object;

    //Do some setup and verify
}

Option Two - Simply register a mock instance of IUnitOfWork with your IoC Container

private Mock<IUnitOfWork> _mockUnitOfWork;

[TestInitialize]
public void Init()
{
    _mockUnitOfWork = new Mock<IUnitOfWork>();

    //Making a lot of assumptions about your IoC here...
    IoC.Register<IUnitOfWork>(_mockUnitOfWork.Object);
}

[TestMethod]
public void DoStuff()
{
    _mockUnitOfWork.Setup( ... );

    //Do some verification
}
like image 91
Josh Avatar answered Sep 25 '22 10:09

Josh


Mock the IUnitOfWork and register it into your container so that it can be resolved.

like image 27
Phill Avatar answered Sep 22 '22 10:09

Phill