I have a Project
entity that has a set of Word
entities within. My WordsRepository
depends on the Project
entity. It should operate over the set of words that the project includes.
public interface IWordsRepository
{
List<Word> FetchAll();
}
public class WordsRepository : IWordsRepository
{
private readonly Project _project;
public WordsRepository(Project project)
{
if (project == null)
throw new ArgumentNullException("project");
this._project = project;
}
public List<Word> FetchAll()
{
// code for retrieveing words for the project from the database
}
}
Now let's dig a little deeper. Here is my ProjectsModel
.
public class ProjectsModel
{
private readonly IProjectsRepository _rep;
private IWordsRepository _wordsRep;
private IProjectsModelObserver _presenter;
// Regular contructor for usual purpose
public ProjectsModel()
{
this._rep = new ProjectsRepository(Program.context);
}
public ProjectsModel(IProjectsRepository repository)
{
this._rep = repository;
}
public virtual void AttachPresenter(IProjectsModelObserver observer)
{
this._presenter = observer;
}
public List<Project> projects
{
get
{
List<Project> tmpList = _rep.FetchAll();
return (tmpList != null) ? tmpList : new List<Project>();
}
}
private Project _selectedProject;
public Project selectedProject
{
get
{
if (_selectedProject == null)
_selectedProject = projects.FirstOrDefault();
return _selectedProject;
}
set
{
if (!projects.Contains(value))
throw new InvalidOperationException("Project not in the Projects list");
_selectedProject = projects[projects.IndexOf(value)];
// Recreating Words repository depending on project
// Here is my issue:
// As I should recreate the Words repository here, passing a new selected project
// how can I mock it and make this class testable?
this._wordsRep = new WordsRepository(this._selectedProject);
if (this._presenter != null)
this._presenter.SelectedProjectChanged(_selectedProject);
}
}
private List<Word> _words;
public List<Word> Words
{
get
{
// Fetching set of words in Project. Just invoking a words repository
}
}
}
When the model's selected project is changed, it should recreate the WordsRepository
, but it isn't testable this way.
How can I mock it?
You need to use a factory to create the new WordsRepository
. As you probably know, whenever you see the word new
in your code, it's probably a good idea to make a Factory class that will give you that instance being requested, because then you can mock the factory to return whatever instance you want at testing time.
So you would change to this:
_WordsRep = WordsRepositoryFactory.CreateNewRepository(_selectedProject);