c# - How to mock IRepository<T>? -
i want mock unit of work interface repositories inside unit test purpose. far able below.
namespace liquid.service.unittest { using liquid.dataaccess.interface; using liquid.domain; using domain.interface; using moq; using system.collections.generic; using system.linq; internal class helper { internal mock<iunitofwork> mockunitofwork(icollection<dummy> dummies = null, icollection<producttype> producttypes = null) { dummies = dummies ?? new list<dummy>(); producttypes = producttypes ?? new list<producttype>(); var dummyrepositorymock = mockdummyrepository(dummies); var producttyperepositorymock = mockproducttyperepository(producttypes); var unitofworkmock = new mock<iunitofwork>(); unitofworkmock.setup(x => x.dummyrepository) .returns(dummyrepositorymock.object); unitofworkmock.setup(x => x.producttyperepository) .returns(producttyperepositorymock.object); return unitofworkmock; } private mock<idummyrepository> mockdummyrepository(icollection<dummy> dummies) { var dummyrepositorymock = new mock<idummyrepository>(); dummyrepositorymock.setup(x => x.findbyid(it.isany<int>())) .returns((int arg1) => dummies.where(x => x.id == arg1).singleordefault()); dummyrepositorymock.setup(x => x.add(it.isany<dummy>())) .callback((dummy arg1) => dummies.add(arg1)); return dummyrepositorymock; } private mock<iproducttyperepository> mockproducttyperepository(icollection<producttype> producttypes) { var producttyperepositorymock = new mock<iproducttyperepository>(); producttyperepositorymock.setup(x => x.findbyid(it.isany<int>())) .returns((int arg1) => producttypes.singleordefault(x => x.id == arg1)); producttyperepositorymock.setup(x => x.add(it.isany<producttype>())) .callback((producttype arg1) => producttypes.add(arg1)); return producttyperepositorymock; } } }
you see i've created 2 method mock dummyrepository , producttyperepository because has same implementation, think redundant every repositories have. below repositories , irepository code.
namespace liquid.dataaccess.interface { using liquid.domain; using system.collections.generic; using system.threading; using system.threading.tasks; public interface idummyrepository : irepository<dummy> { } public interface iproducttyperepository : irepository<producttype> { } public interface irepository<tentity> tentity : class { ilist<tentity> getall(); task<list<tentity>> getallasync(); task<list<tentity>> getallasync(cancellationtoken cancellationtoken); ilist<tentity> pageall(int skip, int take); task<list<tentity>> pageallasync(int skip, int take); task<list<tentity>> pageallasync(cancellationtoken cancellationtoken, int skip, int take); tentity findbyid(object id); task<tentity> findbyidasync(object id); task<tentity> findbyidasync(cancellationtoken cancellationtoken, object id); void add(tentity entity); void update(tentity entity); void remove(tentity entity); } }
how can use same method mock every repositories implementation inherits irepository?
update : test simple add , check below.
[test] public void producttypeservice_add() { // given var producttypedata = new producttype() { id = 1, description = "producttype1" }; // when var unitofworkmock = new helper().mockunitofwork(); var producttypeservice = new producttypeservice(unitofworkmock.object); producttypeservice.add(producttypedata); unitofworkmock.verify(x => x.savechanges()); // assert.that(producttypeservice.findbyid(1) != null); assert.that(producttypeservice.findbyid(2) == null); // when var producttypedata2 = new producttype() { id = 2, description = "producttype2" }; producttypeservice.add(producttypedata2); // assert.that(producttypeservice.findbyid(2) != null); }
i think have on complicated question , solution. don't need interfaces various repositories idummyrepository , iproductrepository if not adding value it.
your data classes
public class dummy { public int id { get; set; } } public class producttype { public int id { get; set; } }
your producttypeservice (i can assume this)
public class producttypeservice { private readonly iunitofwork _unitofwork; public producttypeservice(iunitofwork unitofwork) { _unitofwork = unitofwork; } public void addproducttype(producttype producttype) { _unitofwork.producttypes.add(producttype); } }
your iunitofwork
public interface iunitofwork { irepository<dummy> dummies { get; set; } irepository<producttype> producttypes { get; set; } }
your irepository remains unchanged won't copy paste here!
finally unit test
[testfixture] public class class1 { private mock<iunitofwork> _unitofworkmock; private mock<irepository<dummy>> _dummyrepositorymock; private mock<irepository<producttype>> _producttyperepositorymock; [setup] public void setup() { _unitofworkmock = new mock<iunitofwork>(); _dummyrepositorymock = createmock<dummy>(); _producttyperepositorymock = createmock<producttype>(); _unitofworkmock.setup(u => u.dummies).returns(_dummyrepositorymock.object); _unitofworkmock.setup(u => u.producttypes).returns(_producttyperepositorymock.object); } [test] public void product_type_service_should_add_item_to_the_underlying_repository() { var producttypeservice = new producttypeservice(_unitofworkmock.object); var producttype = new producttype {id = 10}; producttypeservice.addproducttype(producttype); _producttyperepositorymock.verify(r => r.add(it.is<producttype>(p => p.id == producttype.id)), times.once()); } private mock<irepository<t>> createmock<t>() t : class { var mock = new mock<irepository<t>>(); // more common magic here return mock; } }
Comments
Post a Comment