Reputation: 1299
My application consists of various concrete Job-classes (all inheriting from the abstract Job class). In their Run() method they usually call external services. I'd like to test my job classes and mock the service results.
Here's how a typical concrete Run() method looks:
InstallWpJobResult result = new InstallWpJobResult();
WpManager wpManager = new WpManager();
if (!WpManager.InstallWp(Domain, SiteTitle, WpUsername, WpPassword, WpEmail))
result.Error = "Error installing WordPress";
return result;
I'd like the WpManager.InstallWp to return true (in the mocked version). I know how to mock the object and method but how do I make my job use the mocked version? (Right now it creates an instance within the method itself).
Btw I'm using the Moq framework for mocking.
Upvotes: 4
Views: 756
Reputation: 6134
Instantiating concrete classes inside consumer classes goes against one of the SOLID principles (the "D" or "Dependency Injection"). One of the reasons is the one you ran across: testability.
I suggest you make the WpManager
take an instance of IInstallWpJobResult
(note it is an interface) as part of its construction, rather than instantiating one. This way you can easily change the behavior of the class given different IInstallWpJobResult
implementations, e.g. passing in a Mock<IInstallWpJobResult>
with predefined behavior for easier testing.
This will also come in handy once you start using Dependency Injection frameworks to resolve all those dependencies at runtime, since they usually look at the arguments of a constructor to get an idea of dependencies to inject.
Upvotes: 0
Reputation: 27495
A few options:
Quick example of the factory service approach:
public interface IWpManagerFactory
{
WpManager BuildWpManager();
}
public sealed class Tests
{
public void Test()
{
var manager = new Mock<WpManager>();
//Set up mock manager here...
var factory = new Mock<IWpManagerFactory>();
factory.Setup(f => f.BuildWpManager()).Returns(manager.Object);
//Inject factory to class under test and execute the method under test...
}
}
This assumes of course that your WpManager has virtual methods that can be mocked. If not, you'll need to extract an IWpManager interface as well, then mock that instead.
Upvotes: 3