c# - Why is my mock set empty? -
i starting learn unit testing , mocking. i've spent day reading different tutorials, trying find best 1 practice with. i've settled on testing mocking framework (ef6 onwards) using ef6 (modern), seems popular mocking framework (moq). also, quite vanilla , hosted on msdn webset. has decent, right?
i've set project specified in example , running debugger through test examples make sure understand going on. test i'm working through follows:
[testclass] public class querytests { [testmethod] public void getallblogs_orders_by_name() { var data = new list<blog> { new blog { name = "bbb" }, new blog { name = "zzz" }, new blog { name = "aaa" }, }.asqueryable(); var mockset = new mock<dbset<blog>>(); mockset.as<iqueryable<blog>>().setup(m => m.provider).returns(data.provider); mockset.as<iqueryable<blog>>().setup(m => m.expression).returns(data.expression); mockset.as<iqueryable<blog>>().setup(m => m.elementtype).returns(data.elementtype); mockset.as<iqueryable<blog>>().setup(m => m.getenumerator()).returns(data.getenumerator()); var mockcontext = new mock<bloggingcontext>(); mockcontext.setup(c => c.blogs).returns(mockset.object); var service = new blogservice(mockcontext.object); //test code here var blogs = service.getallblogs(); assert.areequal(3, blogs.count); assert.areequal("aaa", blogs[0].name); assert.areequal("bbb", blogs[1].name); assert.areequal("zzz", blogs[2].name); } }
it simple , lead believe understanding unit testing , mocking framework. cool! decide perform experiment validate myself, inserting service.addblog("ado.net blog", "http://blogs.msdn.com/adonet");
(from previous example) above testmethod, after service instantiated.
i expect step past var blogs = service.getallblogs();
, blogs should contain new entry, not. contains 3 initialization of data
.
what going on here? shouldn't code insert blog record data
object, , pulling when calling getallblogs()
? perhaps not understanding idea of mocks properly?
why mock set empty?
because didn't configure (setup) take action when insert data it. when mock created "loses" logic present on original class , marked virtual
. moq overrides such methods later can configure them (return value, throw, etc).
naturally, can setup add
method insert data data
blog list:
var mockset = new mock<dbset<blog>>(); mockset.setup(m => m.add<it.isany<blog>()).callback(blog => data.add(blog));
when add
method invoked on dbset
(preferrably via call service) configured version of add
take on , insert blog data list (callback
method tells moq "invoke code" when mocked method called).
you try prevent overriding of add
using callbase parameter. however, might not work dbset not aware of list
existence, you'll have configure more heavily then.
on final note, once experiment crystallizes should realize configuring add
won't necessary because won't checking whether blog added via getallblogs
method rather verification on mock itself:
mockset.verify(m => m.add(it.isany<blog>()), times.once());