c# - Using Moq and Xunit to test interfaces -
i new xunit , moq. trying understand both test frameworks , preparing unit test cases. using dependency injection inject interfaces.
i testing following interfaces
using system.collections.generic; using zeiss.imt.mccneo.settings.entities; namespace zeiss.imt.mccneo.settings.data.interface { public interface iprofilesrepository { ilist<profile> getallprofiles(); ilist<profile> getprofilesmatchinguserid(string userid); ilist<profile> getprofilesforuseridwithsettingname(string userid, string settingname); } }
the implementation class
using system; using system.collections.generic; using zeiss.imt.mccneo.settings.data.interface; using zeiss.imt.mccneo.settings.entities; using system.linq; using zeiss.imt.mccneo.settings.data.singleton; using zeiss.imt.mccneo.settings.utilities; namespace zeiss.imt.mccneo.settings.data.repository { public class profilesrepository : iprofilesrepository { private iprofiledatarepository _profiledatarepository { get; set; } public profilesrepository(iprofiledatarepository profiledatarepository) { _profiledatarepository = profiledatarepository; } public ilist<profile> getallprofiles() { return _profiledatarepository.get(); } public ilist<profile> getprofilesmatchinguserid(string userid) { if (string.isnullorwhitespace(userid)) throw new argumentexception("user id cannot null"); return _profiledatarepository.get().where(puid => puid.userid.tolower() == userid.tolower()).tolist<profile>(); } public ilist<profile> getprofilesforuseridwithsettingname(string userid, string settingname) { if (string.isnullorwhitespace(userid) || string.isnullorwhitespace(settingname)) throw new argumentexception("user id or settingname cannot null"); var profileswithsettings = _profiledatarepository.get().where(p => p.userid.tolower() == userid.tolower() & p.settings.any(s => s.name.tolower() == settingname.tolower())); return profileswithsettings.tolist(); } } }
the data repository deals data loading , data saving file
using system; using system.collections.generic; using zeiss.imt.mccneo.settings.entities; namespace zeiss.imt.mccneo.settings.data.singleton { public interface iprofiledatarepository { list<profile> get(); list<profile> get(func<profile, bool> filter); void save(list<profile> profilestosave); } } using system; using system.collections.generic; using zeiss.imt.mccneo.settings.entities; using zeiss.imt.mccneo.settings.utilities; using system.linq; namespace zeiss.imt.mccneo.settings.data.singleton { public class profiledatarepository : iprofiledatarepository { private static list<profile> profiles; public irepository _repository { get; set; } public profiledatarepository(irepository repository) { _repository = repository; if (profiles == null) { profiles = repository.get<profile>(); } } public list<profile> get() { return profiles; } public list<profile> get(func<profile, bool> filter) { return profiles.where(filter).tolist(); } public void save(list<profile> profilestosave) { profiles = profilestosave; _repository.save<list<profile>>(profiles); } } }
i trying mock profile entity , pass mocked interfaces. but, still lacking understanding on how mock interfaces , pass data entities.
entity class namespace zeiss.imt.mccneo.settings.entities { public class profile { public string userid { get; set; } public string username { get; set; } public list<setting> settings { get; set; } } } test class using moq; using system; using system.collections.generic; using system.text; using zeiss.imt.mccneo.settings.data.interface; using zeiss.imt.mccneo.settings.data.singleton; using zeiss.imt.mccneo.settings.entities; namespace zeiss.imt.mccneo.settings.tests { public class profilesservicetests { private readonly mock<iprofiledatarepository> profiledataprovider; private readonly mock<iprofilesrepository> profilesprovider; public profilesservicetests() { profiledataprovider = new mock<iprofiledatarepository>(); profilesprovider = new mock<iprofilesrepository>(); } public void getprofilesmatchinguserid_whenpassednull_return_exception() { list<setting> settings = new list<setting>() { new setting(){ name = "refreshinterval", value = { }, type = "string", encrypted = true, readonly = true, createdon = new datetime(), modifiedon = new datetime(), valid = true, enabled = true, description = "protocol archive view renwal interval in seconds. minimum value = 300 maximum value = 28800" } }; profile profile = new profile() { userid = "admin", username = "admin", settings = settings }; list<profile> profiles = new list<profile>() { profile }; profiledataprovider.setup(x => x.get()).returns(profiles); profilesprovider.setup(x => x.getprofilesmatchinguserid(null)).returns(new nullreferenceexception()); } } }
kindly, suggest.
it feels want test (or lot) in 1 class. keep in mind don't need make integration tests (yet).
first take @ profilesrepository
.
we need
public class profilerepositorytests { //this class reposible handle data iprofiledatarepository private readonly profilesrepository _profilesrepository; private readonly mock<iprofiledatarepository> _moqprofiledataprovider; public profilerepositorytests() { _moqprofiledataprovider = new mock<iprofiledatarepository>(); _profilesrepository = new profilesrepository(_moqprofiledataprovider.object); } [fact] public void get_succes_noprofiles() { _moqprofiledataprovider.setup(x => x.get()).returns(new list<profile>()); var profiles = _profilesrepository.getallprofiles(); assert.areequal(0, profiles.count); } [fact] public void get_succes_allprofiles() { _moqprofiledataprovider.setup(x => x.get()).returns(new list<profile> { new profile {userid = "123"} }); var profiles = _profilesrepository.getallprofiles(); assert.areequal(1, profiles.count); assert.areequal("123", profiles.first().userid); //test more properties } [fact] public void getprofilesmatchinguserid_userid_null_throws_error() { exception ex = assert.throws<argumentexception>(() => _profilesrepository.getprofilesmatchinguserid(null)); } }
this doesn't complete tests, gives idea how can continue. remember, seperate class/unit tests etc etc. each test should check 1 exception. remember, unit test tests 1 thing, 1 situation. if code throwing 2 different exceptions, it's can't doing under same conditions.
good luck!
Comments
Post a Comment