Question regarding mocking framework C# and unit tests
I have a class that reads a pop3 email server. I want to write some unit tests for the containing class, so I need to mock the POP3 server classes. I am using OpenPOP.Net. So I hav开发者_开发知识库e a constructor like this:
EmailHost(string email, string password, string pop3Address, int port)
... etc....
Then later I have a connect class:
private void Connect()
{
_pop3 = new Pop3Client();
etc...
So the reference to the Pop client is buried in the guts of the class. To be able to mock it I need to do some funky stuff, since as making EmailHost a generic on the Pop3Client, or adding some function with a default to do the above line:
public EmailHost<PopClass>(...)
or
public EmailHost(... params, Func popGenerate = () => new Pop3Client())
So it seems I have to compromise my constructor a little to make it work with mock. (Obviously I'd define an IPop3Client or so forth.)
Any thoughts on how to do this correctly?
EDIT:
jOk provides an interesting answer, problem is that it doesn't fit well within the structure of what I am doing. In this particular case I need to handle multiple email addresses in the Pop client, and the are added dynamically. Consequently, as you add each email address, you need to create a new Pop3Client. Additionally, I want to hide the implementation of the POP3 itself, so that they user doesn't need to know about it as much as possible.
Any other thoughts on this?
Thanks for you input btw.
I think you're close.
Instead of passing in all those arguments that are eventually going to be used to create an instance of Pop3Client, consider injecting an instance of Pop3Client.
public EmailHost(IPop3Client client) {
}
By doing this, you're removing your EmailHost class from the responsibility of creating the Pop3Client object. This responsibility is instead shifted somewhere else, most commonly to an IoC container.
I can't tell from the code you posted whether Pop3Client is based on an interface. If it is, great, you can just mock/stub it in your test and inject the dependency. If not, then there's more work involved in manipulating it so that it'll work in this scenario. It can be as simple as writing a wrapper (and corresponding interface) around the class that exposes the methods that you're using inside of EmailHost. This can then be used in place of IPop3Client in the example above.
Does that make sense? Let me know if you need more guidance.
use something like Castle Windsor to do service location. If you don't want to change the constructor, call Resolve on the container but that's not the proper way of doing it. Putting the dependency in the constructor is fine and suggested.
I believe Moles will let you override the _pop3 private local variable without any code changes:
http://research.microsoft.com/en-us/projects/pex/downloads.aspx
精彩评论