I am building an applications in .net/c#/Entity Framework that uses a layered architecture. The applications interface to the outside world is a WCF service Layer. Underneath this layer I have the BL, Shared Library and the DAL.
Now, in order to make the business logic in my application testable, I am trying to introduce separation of concerns, loose coupling and high cohesion in order to be able to inject dependencies while testing.
I need some pointers as to if my approach described below is good enough or if I should be decoupling the code even further.
The following code snippet is used to query a database using dynamic linq. I need to use dynamic linq since I dont know the name of the table or the fields to query until runtime. The code first parses json parameters into types objects, then builds the query using these parameters, and finally the query is execute and the result is returned
Here is the GetData function that is used in the test below
IQueryHelper helper = new QueryHelper(Context.DatabaseContext);
//1. Prepare query
LinqQueryData queryData = helper.PrepareQueryData(filter);
//2. Build query
IQueryable query = helper.BuildQuery(queryData);
//3. Execute query
List<dynamic> dalEntities = helper.ExecuteQuery(query);
Here is the high level definion of the query helper class in DAL and its interface
public interface IQueryHelper
{
LinqQueryData PrepareQueryData(IDataQueryFilter filter);
IQueryable BuildQuery(LinqQueryData queryData);
List<dynamic> ExecuteQuery(IQueryable query);
}
public class QueryHelper : IQueryHelper
{
..
..
}
Here is the test that uses the logic as described above. The test constructor injects the mocked db into Context.DatabaseContext
[TestMethod]
public void Verify_GetBudgetData()
{
Shared.Poco.User dummyUser = new Shared.Poco.User();
dummyUser.UserName = "dummy";
string groupingsJSON = "[\"1\",\"44\",\"89\"]";
string valueTypeFilterJSON = "{1:1}";
string dimensionFilter = "{2:[\"200\",\"300\"],1:[\"3001\"],44:[\"1\",\"2\"]}";
DataQueryFilter filter = DataFilterHelper.GetDataQueryFilterByJSONData(
new FilterDataJSON()
{
DimensionFilter = dimensionFilter,
IsReference = false,
Groupings = groupingsJSON,
ValueType = valueTypeFilterJSON
}, dummyUser);
FlatBudgetData data = DataAggregation.GetData(dummyUser, filter);
Assert.AreEqual(2, data.Data.Count);
//min value for january and february
Assert.AreEqual(50, Convert.ToDecimal(data.Data.Count > 0 ? data.Data[0].AggregatedValue : -1));
}
To my questions
- Is this Business layer logic "good enough" or what more can be done to achieve loose coupling, high cohesion and testable code?
- Should I inject the data context to query in the constructor? Note that the QueryHelper definitions is located in DAL. The code that uses it is located in BL
Please let me know if I should post additional code for clarity. I'm mostly interested if the interface IQueryHelper is sufficient..
I generally use IServices, Services, and MockServices.
IServices:
MockServices:
Services:
Unit Test:
CodeBehnd:
ViewModel: