c# - How do I register decorators with AutoFixture? -
the decorator pattern demonstrates how can extend behaviour of component without modifying underlying implementation. means have 2 components implement same interface. there way register
these in autofixture can still refer component polymorphically interface?
a code example my meaning. let's assume want decorate icomponent
loggingcomponent
interface icomponent { void dostuff(); } class component : icomponent { public void dostuff() { // amazing! } } class loggingcomponent : icomponent { private readonly icomponent _component; public loggingcomponent(icomponent component) { _component = component; } public void dostuff() { console.writeline("calling dostuff()"); _component.dostuff(); } }
how go both registering loggingcomponent
icomponent
, creating loggingcomponent
without circular dependency?
what's alternative registering loggingcomponent
way:
_fixture.register<icomponent>(_fixture.create<loggingcomponent>);
and trying create instance of icomponent
using code:
var component = _fixture.create<icomponent>();
which results in objectcreationexception exception being thrown:
autofixture unable create instance of type ploeh.autofixture.kernel.seededrequest because traversed object graph contains circular reference. information circular path follows below. correct behavior when fixture equipped throwingrecursionbehavior, default. ensures being made aware of circular references in code. first reaction should redesign api in order rid of circular references. however, if not possible (most because parts or of api delivered third party), can replace default behavior different behavior: on fixture instance, remove throwingrecursionbehavior fixture.behaviors, , instead add instance of omitonrecursionbehavior.
you need freeze icomponent
first.
then, autofixture re-use same frozen icomponent
instance when creating loggingdecorator
class.
here 2 ways of doing this:
using autofixture auto mocking:
pm> install-package autofixture.automoq [fact] public void usingautofixtureautomoq() { var fixture = new fixture() .customize(new automoqcustomization()); var expected = fixture.freeze<mock<icomponent>>().object; var decorator = fixture.create<loggingcomponent>(); var actual = decorator.component; assert.equal(expected, actual); }
using autofixture auto mocking , xunit.net data theories:
pm> install-package autofixture.xunit pm> install-package autofixture.automoq [theory, testconventions] public void usingautofixtureautomoqwithxunittheories( [frozen]mock<icomponent> inner, loggingcomponent decorator) { var expected = inner.object; var actual = decorator.component; assert.equal(expected, actual); }
testconventions
attribute class defined as:
internal class testconventionsattribute : autodataattribute { internal testconventionsattribute() : base( new fixture().customize( new automoqcustomization())) { } }
note: compile , run above test(s), add inspection property icomponent
loggingdecorator
.
Comments
Post a Comment