Reputation: 27011
I have a method inside which it calls the .NET XDocument.Load() method to load the xml data from a url. I'd like to make my class unit testable.
So how to make that call mockable/unit testable?
private void ProcessData(string url)
{
// todo: make this mockable
var xDocument = XDocument.Load(url);
// the rest of the code
}
One solution I've used is to inject an xmlUrlLoader into the clas like below:
private readonly Func<string, XDocument> _xmlUrlLoader;
public MyConstructor(Func<string,XDocument> xmlUrlLoader)
{
_xmlUrlLoader = xmlUrlLoader;
}
private void ProcessData(string url)
{
// todo: make this mockable
var xDocument = this._xmlUrlLoader(url);
// the rest of the code
}
Is there any better way?
Upvotes: 3
Views: 407
Reputation: 3002
I agree that injecting a loader is the correct approach I'm not sure why it would be of type Func
I would expect an interface along the lines of
public interface IXmlDocumentLoader
{
XDocument LoadDocument(string url);
}
and then your code would look like
private readonly IXmlDocumentLoader _xmlUrlLoader;
public MyConstructor(IXmlDocumentLoader xmlUrlLoader)
{
_xmlUrlLoader = xmlUrlLoader;
}
private void ProcessData(string url)
{
var xDocument = this._xmlUrlLoader(url);
// the rest of the code
}
But I think that for reasons of separation of concerns the document loader should definitely be in its own class.
Upvotes: 3
Reputation: 108800
I prefer separating logic from accessing resources. In your case I'd pass the document to the processing function:
void ProcessData(XDocument xDocument);
You can test that function without mocking anything. Then if you want you can add a thin wrapper on top that does the loading.
void ProcessUrl(string url);
{
var xDocument = XDocument.Load(url);
ProcessData(xDocument);
}
You can use mocking to unit test the wrapper, but personally I don't see much gain in that. I prefer to exercise those wrappers only as part of integration tests.
Upvotes: 3