How to approach unit testing of private methods?
I have a class that loads Employee data into a database. Here is a sample:
>
public class EmployeeFacade
{
public Employees EmployeeRepository = new Employees();
public TaxDatas TaxRepository = new TaxDatas();
public Accounts AccountRepository = new Accounts();
//and so on for about 20 more repositories etc.
public bool LoadAllEmployeeData(Employee employee)
{
if (employee == null)
throw new Exception("...");
bool exists = EmployeeRepository.FetchExisting(emps.Id);
if (!exists)
{
EmployeeRepository.AddNew();
}
try
{
EmployeeRepository.Id = employee.Id;
EmployeeRepository.Name = employee.EmployeeDetails.PersonalDetails.Active.Names.FirstName;
EmployeeRepository.SomeOtherAttribute;
}
catch() {}
try
{
emps.Save();
}
catch(){}
try
{
LoadorUpdateTaxData(employee.TaxData);
}
catch() {}
try
{
LoadorUpdateAccountData(employee.AccountData);
}
catch() {}
... etc. for about 20 more other employee objects
}
private bool LoadorUpdateTaxData(employeeId, TaxData taxData)
{
if (taxData == null)
throw new Exception("...");
...same format as above but using AccountRepository
}
private bool LoadorUpdateAccountData(employee.TaxData)
{
...same format as above but using TaxRepository
}
}
I am writing an application to take serialised objects(e.g. Employee above) and load the data to the database.
I have a few design question that I would like opinions on:
A - I am calling this class "EmployeeFacade" because I am (attempting?) to use the facade pattern. Is it good practace to name the pattern on the class name?
B - Is it good to call the concrete entities of my DAL layer classes "Repositories" e.g. "EmployeeRepository" ?
C - Is using the repositories in this way sensible or should I create a method on the repository itself to take, say, the Employee and then load the data from there e.g. EmployeeRepository.LoadAllEmployeeData(Employee employee)? I am aim for cohesive class and but this will requrie the repository to have knowledge of the Employee object which may not be good?
D - Is there any nice way around of not having to check if an object is null at the begining of each method?
E - I have a EmployeeRepository, TaxRepository, AccountRepository declared as public for unit testing purpose. These are really private enities but I need to be able to substitute these with stubs so that the won't write to my database(I overload the save() method to do nothing). Is there anyway around this or do I have to expose them?
F - How can I test the private methods - or is this done (something tells me it's not)?
G- "emps.Name = employee.EmployeeDetails.PersonalDetails.Active.Names.FirstName;" this breaks the Law of Demeter but how do I adjust my objects to abide by the law?
A - I wouldn't call it XXXFacade, but something more meaningful (which may in fact mean you should call it XXXFacade)
B - I would call them XXXRepository
C - I don't really understand your model here - you're passing in an Employee object and assigning its values to the equivilent values in EmployeeRepository. The Repository shouldn't contain data fields - each instance of the repository does not represent a row in the database. The Repository is a way of getting data in and out of the database, by operating on collections of entities from the database (ie: Repository is the table, Entities are the rows). I would expect the Repository object to have a Save method which takes an Employee object as a parameter and it persists it to the database. As well as a Load method which takes an Id and returns and Employee:
Employee myEmployee = repository.Load(112345);
myEmployee.Name = "New Name";
repository.Save(myEmployee);
The Repository base class doesn't need to know about the specific implementation of the Employee class, through the use of generics and polymorphism. Take a look at Sh#rpArchitecture for a good example of this pattern.
D - yes, put that common logic in an abstract base class (Repository)
E - don't make them public if they should be private. If you need the use the logic of the repository in your unit tests to simulate fetching data, implement a common interface and then mock that interface out in your tests. You don't need to test that the repository returns the correct data since data is transient and inconsistent in reality. Better to fake it and test your behaviour does what you expect on precanned data from a mock repository.
F - Don't. Test behaviour not implementation.
G - I don't think this issue exists if you examine your architecture as described above.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With