c# - Unit Testing Queries that passes Expression<Func> to Repository -
c# - Unit Testing Queries that passes Expression<Func<T,bool>> to Repository -
i'm having issue testing querying side of architecture i'm calling repository expects expression<func<t, bool>>
parameter filtering. trying understand article, mark saying utilize stubs queries instead.
lets have query handler:
public class getuserbyemailqueryhandler : iqueryhandler<getuserbyemailquery, user> { private readonly igenericrepository<user> userrepository; public getuserbyemailqueryhandler(igenericrepository<user> userrepository) { this.userrepository = userrepository; } public user handle(getuserbyemailquery query) { homecoming this.userrepository.find(u => u.email == query.email && u.islockedout == false); } }
now test going this:
[fact] public void correctly_returns_result() { // arrange var id = guid.newguid(); var email = "test@test.com"; var userrepositorymock = new mock<igenericrepository<user>>(); userrepositorymock.setup( r => r.find(it.isany<expression<func<user, bool>>>())).returns(new user { userid = id }).verifiable(); // deed var query = new getuserbyemailquery(email); var queryhandler = new getuserbyemailqueryhandler(userrepositorymock.object); var item = queryhandler.handle(query); // assert userrepositorymock.verify(); assert.equal(id, item.userid); }
to me, test useless, using it.isany<expression<func<user, bool>>>()
filtering @ all. filter crucial business logic needs tested. how can test look this? 1 of reasons why generic repository bad , should utilize specific repository take filter parameters needed? if case, i'll moving look 1 layer other , i'd still need test it
if should utilize stubs mark said in blog, there examples out there? supposed run query on in-memory list used validate filter look correct?
is 1 of reasons why generic repository bad
yes, is. additionally, if want follow solid principles of ood (not must, useful in order understand consequences of design decisions), "clients […] own abstract interfaces" (agile principles, patterns, , practices, chapter 11). thus, interface used client should defined in terms of client needs, not general-purpose library exposes.
in particular case, looks getuserbyemailqueryhandler
needs ability query based on email address, define reader interface this:
public interface iuserreader { user findbyemail(string email); }
this turns getuserbyemailqueryhandler
this:
public class getuserbyemailqueryhandler : iqueryhandler<getuserbyemailquery, user> { private readonly iuserreader userrepository; public getuserbyemailqueryhandler(iuserreader userrepository) { this.userrepository = userrepository; } public user handle(getuserbyemailquery query) { homecoming this.userrepository.findbyemail(query.email); } }
at point, getuserbyemailqueryhandler
class degenerate should consider whether adds value.
the filter crucial business logic needs tested. how can test look this?
that depends on where want business logic execute in final system. test filter running in memory, if plan on executing on database server, you'll have involve database in automated tests. tends suck, case why programmers looking alternatives relational databases.
sorry, if there's solution particular problem, don't know is.
personally, design scheme don't rely on complicated filter expressions, on simple filter expressions can treat humble objects.
c# domain-driven-design repository-pattern
Comments
Post a Comment