|
View:
New views
4 Messages
—
Rating Filter:
Alert me
|
|
|
Creating dummiesAs I've discussed with some of you before I've created a mocking-framework of my own and while this might be an utterly stupid thing to do in the general sence my motivation for doing this was mainly to have a "playground" where I could try out new ideas but also to have a framework that removes the distinction of stubs and mocks, instead everything are "fakes".
One of these more experimental features that - as far as I know - does not exist anywhere else is the ability to "tell the framework" how to create fakes. This means that although for example the string class can not be proxied (by DynamicProxy2 which is the proxy generation framework I use) you can tell the framework that whenever a fake of the type string is requested just return for example the string "foo". When this is done you can use the following in your tests: var s = A.Fake<string>(); //s will now contain "foo" In the case of string this is probably not so useful, but say that you have some kind of DTO: public sealed class SomeDTO { public string StringValue; public int IntValue; } This can not be proxied but you can tell the framework to create fakes of this type, the easiest way is using MEF and the type FakeDefinition<T> provided in the FakeItEasy.Mef-assembly: public class SomeDTODefinition : FakeDefinition<SomeDTO> { protected override SomeDTO CreateFake(IEnumerable<object> arguments) { return new SomeDTO() { IntValue = 10, StringValue = "foo" }; } } This will automatically be picked up by MEF and used by FakeItEasy so that in your test you can now use the following: [Test] public void Something_should_fail_when_int_value_is_90() { var dto = A.Fake<SomeDTO>(); dto.IntValue = 90; Assert.Throws<InvalidOperationException>(() => Something(dto)); } My concern here is that maybe this is a bit too transparent, you don't REALLY know when calling A.Fake<SomeType>() if a proxy will be returned or not. This leads me to think that maybe I should have another syntax for creating these fakes that are really dummies, something like: var dto = A.Dummy<SomeDTO>(); The Dummy-method would return the user defined dummy if available and a proxy otherwise. On the other hand the thing I really wanted to solve when I started out was to remove the distinction between mocks and stubs so I'm not sure it's very bright to introduce the distinction between dummies and fakes. Any thoughts? Another related feature is the ability to specify default configurations of fake objects described here: http://ondevelopment.blogspot.com/2009/11/configuring-fake-objects-on-global.html |
|
|
Re: Creating dummiesthe default configurations for fakes feels a bit like the
"Swap.AllInstance<T>" in Isolator. I find that a very valuable feature indeed - since it removes the dependency of the test from how many instances will be created (so it's less fragile if the production code changes to use more instances for example) On Sun, Nov 1, 2009 at 2:07 PM, Patrik <patrik@...> wrote: > As I've discussed with some of you before I've created a mocking-framework > of my own and while this might be an utterly stupid thing to do in the > general sence my motivation for doing this was mainly to have a "playground" > where I could try out new ideas but also to have a framework that removes > the distinction of stubs and mocks, instead everything are "fakes". > > One of these more experimental features that - as far as I know - does not > exist anywhere else is the ability to "tell the framework" how to create > fakes. > > This means that although for example the string class can not be proxied > (by DynamicProxy2 which is the proxy generation framework I use) you can > tell the framework that whenever a fake of the type string is requested just > return for example the string "foo". When this is done you can use the > following in your tests: > > var s = A.Fake<string>(); > //s will now contain "foo" > > In the case of string this is probably not so useful, but say that you have > some kind of DTO: > > public sealed class SomeDTO > { > public string StringValue; > public int IntValue; > } > > This can not be proxied but you can tell the framework to create fakes of > this type, the easiest way is using MEF and the type FakeDefinition<T> > provided in the FakeItEasy.Mef-assembly: > > public class SomeDTODefinition : FakeDefinition<SomeDTO> > { > protected override SomeDTO CreateFake(IEnumerable<object> arguments) > { > return new SomeDTO() { IntValue = 10, StringValue = "foo" }; > } > } > > This will automatically be picked up by MEF and used by FakeItEasy so that > in your test you can now use the following: > > [Test] > public void Something_should_fail_when_int_value_is_90() > { > var dto = A.Fake<SomeDTO>(); > dto.IntValue = 90; > > Assert.Throws<InvalidOperationException>(() => > Something(dto)); > } > > My concern here is that maybe this is a bit too transparent, you don't > REALLY know when calling A.Fake<SomeType>() if a proxy will be returned or > not. This leads me to think that maybe I should have another syntax for > creating these fakes that are really dummies, something like: > > var dto = A.Dummy<SomeDTO>(); > > The Dummy-method would return the user defined dummy if available and a > proxy otherwise. On the other hand the thing I really wanted to solve when I > started out was to remove the distinction between mocks and stubs so I'm not > sure it's very bright to introduce the distinction between dummies and > fakes. > > Any thoughts? > > Another related feature is the ability to specify default configurations of > fake objects described here: > http://ondevelopment.blogspot.com/2009/11/configuring-fake-objects-on-global.html > > > > ------------------------------------ > > Yahoo! Groups Links > > > > -- Thanks, Roy Osherove www.TypeMock.com - Unit Testing, Plain Smart Author of "The Art Of Unit Testing" (http://ArtOfUnitTesting.com ) A blog for team leaders: http://5Whys.com my .NET blog: http://www.ISerializable.com Twitter: http://twitter.com/RoyOsherove +972-524-655388 (GMT+2) |
|
|
RE: Creating dummiesIt looks like the generator takes an enumeration of objet arguments. Are
those supplied by Fake<T>(...)? How about making Fake<T> take an optional single object (intended to be an anonymous structure)? Then the generator method can use the contents of the object to modify its behavior for a given purpose. To make it easier to use, pass the generator a wrapper for the object with typed member accessors. (Or if using .Net 4.0, make it dynamic.) Then we can have: var fake = Fake<SomeDTO>(new { IntValue = 1, StringValue = "2" }); public class SomeDTODefinition : FakeDefinition<SomeDTO> { protected override SomeDTO CreateFake(IFakeArguments args) { return new SomeDTO() { IntValue = args.GetValue<int>("IntValue"), StringValue = args.GetValueOrDefault<string>("StringValue", "default") }; } } You don't really need to bring MEF into the picture. The user could always specify the fake generator type as an additional type parameter to Fake. The advantage is that it will be clearer in the tests where the fakes are coming from. It will also be easier to make use of multiple fake generators for the same type without ambiguity. // use SimpleDTODefinition as a generator for SomeDTO fakes. var fake1 = Fake<SomeDTO, SimpleDTODefinition>(); // use ComplexDTODefinition as a generator for SomeDTO fakes.var fake2 = Fake<SomeDTO, ComplexDTODefinition>(new { SomeOption = "foo" }); Jeff. -----Original Message----- From: altdotnet@... [mailto:altdotnet@...] On Behalf Of Patrik Sent: Sunday, November 01, 2009 4:07 AM To: altdotnet@... Subject: [altdotnet] Creating dummies As I've discussed with some of you before I've created a mocking-framework of my own and while this might be an utterly stupid thing to do in the general sence my motivation for doing this was mainly to have a "playground" where I could try out new ideas but also to have a framework that removes the distinction of stubs and mocks, instead everything are "fakes". One of these more experimental features that - as far as I know - does not exist anywhere else is the ability to "tell the framework" how to create fakes. This means that although for example the string class can not be proxied (by DynamicProxy2 which is the proxy generation framework I use) you can tell the framework that whenever a fake of the type string is requested just return for example the string "foo". When this is done you can use the following in your tests: var s = A.Fake<string>(); //s will now contain "foo" In the case of string this is probably not so useful, but say that you have some kind of DTO: public sealed class SomeDTO { public string StringValue; public int IntValue; } This can not be proxied but you can tell the framework to create fakes of this type, the easiest way is using MEF and the type FakeDefinition<T> provided in the FakeItEasy.Mef-assembly: public class SomeDTODefinition : FakeDefinition<SomeDTO> { protected override SomeDTO CreateFake(IEnumerable<object> arguments) { return new SomeDTO() { IntValue = 10, StringValue = "foo" }; } } This will automatically be picked up by MEF and used by FakeItEasy so that in your test you can now use the following: [Test] public void Something_should_fail_when_int_value_is_90() { var dto = A.Fake<SomeDTO>(); dto.IntValue = 90; Assert.Throws<InvalidOperationException>(() => Something(dto)); } My concern here is that maybe this is a bit too transparent, you don't REALLY know when calling A.Fake<SomeType>() if a proxy will be returned or not. This leads me to think that maybe I should have another syntax for creating these fakes that are really dummies, something like: var dto = A.Dummy<SomeDTO>(); The Dummy-method would return the user defined dummy if available and a proxy otherwise. On the other hand the thing I really wanted to solve when I started out was to remove the distinction between mocks and stubs so I'm not sure it's very bright to introduce the distinction between dummies and fakes. Any thoughts? Another related feature is the ability to specify default configurations of fake objects described here: http://ondevelopment.blogspot.com/2009/11/configuring-fake-objects-on-global .html ------------------------------------ Yahoo! Groups Links |
|
|
Re: Creating dummiesHi Jeff. Thanks for your comments.
First of all the MEF-things are all in an assembly of its own and is completely optional, it's just an extra abstraction on top of the real infrastructure that allows for hooking into the creation process. There is an interface called IFakeObjectContainer with the method "bool TryCreateFakeObject(Type typeOfFakeObject, IEnumerable<object> arguments, out object fakeObject);" and the developer can through opening a new "fake scope" override the current container at any time. This would allow for the scenario that you're mentioning where you have specific multiple fake generators for the same type. using (Fake.CreateScope(new MyContainer()) { A.Fake<IFoo>(); // Will now resolve from MyContainer if available. } The public api is something like the following: A.Fake<T>() A.Fake<T>(Expression<Func<T>> argumentsForConstructor) A.Fake<T>(IEnumerable<object> argumentsForConstructor) These methods are what will eventually call the TryCreateFakeObject-method of the fake container so changing input parameters into the container would mean that I would have to either create an overload that takes the object parameter or change the other overloads. But then again, maybe I should. What do you think would it be a good thing to change the signature for the overload that takes an enumerable into one that takes an anonymous type? To explain the overload that take and expression as argumentsForConstructor which may not be to obvious, the expression supplied there should contain a call to the constructor of the type you're faking, however since this is an expression it will never be invoked but the argument values will be "sucked out of it" and passed down to the container or proxy generator. The good thing about this is that it's refactor friendly. Like this: A.Fake<SomeType>(() => new SomeType("constructor argument", "another argument")); I really like your idea of the anonymous type and I'll sit down and thing about what I can come up with. Cheers, Patrik --- In altdotnet@..., "Jeff Brown" <jeff.brown@...> wrote: > > It looks like the generator takes an enumeration of objet arguments. Are > those supplied by Fake<T>(...)? > > How about making Fake<T> take an optional single object (intended to be an > anonymous structure)? Then the generator method can use the contents of the > object to modify its behavior for a given purpose. To make it easier to > use, pass the generator a wrapper for the object with typed member > accessors. (Or if using .Net 4.0, make it dynamic.) > > Then we can have: > > var fake = Fake<SomeDTO>(new { IntValue = 1, StringValue = "2" }); > > public class SomeDTODefinition : FakeDefinition<SomeDTO> { > protected override SomeDTO CreateFake(IFakeArguments args) > { > return new SomeDTO() { IntValue = args.GetValue<int>("IntValue"), > StringValue = args.GetValueOrDefault<string>("StringValue", "default") }; > } > } > > You don't really need to bring MEF into the picture. The user could always > specify the fake generator type as an additional type parameter to Fake. > The advantage is that it will be clearer in the tests where the fakes are > coming from. It will also be easier to make use of multiple fake generators > for the same type without ambiguity. > > // use SimpleDTODefinition as a generator for SomeDTO fakes. > var fake1 = Fake<SomeDTO, SimpleDTODefinition>(); > > // use ComplexDTODefinition as a generator for SomeDTO fakes.var fake2 = > Fake<SomeDTO, ComplexDTODefinition>(new { SomeOption = "foo" }); > > Jeff. > > -----Original Message----- > From: altdotnet@... [mailto:altdotnet@...] On Behalf > Of Patrik > Sent: Sunday, November 01, 2009 4:07 AM > To: altdotnet@... > Subject: [altdotnet] Creating dummies > > As I've discussed with some of you before I've created a mocking-framework > of my own and while this might be an utterly stupid thing to do in the > general sence my motivation for doing this was mainly to have a "playground" > where I could try out new ideas but also to have a framework that removes > the distinction of stubs and mocks, instead everything are "fakes". > > One of these more experimental features that - as far as I know - does not > exist anywhere else is the ability to "tell the framework" how to create > fakes. > > This means that although for example the string class can not be proxied (by > DynamicProxy2 which is the proxy generation framework I use) you can tell > the framework that whenever a fake of the type string is requested just > return for example the string "foo". When this is done you can use the > following in your tests: > > var s = A.Fake<string>(); > //s will now contain "foo" > > In the case of string this is probably not so useful, but say that you have > some kind of DTO: > > public sealed class SomeDTO > { > public string StringValue; > public int IntValue; > } > > This can not be proxied but you can tell the framework to create fakes of > this type, the easiest way is using MEF and the type FakeDefinition<T> > provided in the FakeItEasy.Mef-assembly: > > public class SomeDTODefinition : FakeDefinition<SomeDTO> { > protected override SomeDTO CreateFake(IEnumerable<object> arguments) > { > return new SomeDTO() { IntValue = 10, StringValue = "foo" }; > } > } > > This will automatically be picked up by MEF and used by FakeItEasy so that > in your test you can now use the following: > > [Test] > public void Something_should_fail_when_int_value_is_90() > { > var dto = A.Fake<SomeDTO>(); > dto.IntValue = 90; > > Assert.Throws<InvalidOperationException>(() => > Something(dto)); > } > > My concern here is that maybe this is a bit too transparent, you don't > REALLY know when calling A.Fake<SomeType>() if a proxy will be returned or > not. This leads me to think that maybe I should have another syntax for > creating these fakes that are really dummies, something like: > > var dto = A.Dummy<SomeDTO>(); > > The Dummy-method would return the user defined dummy if available and a > proxy otherwise. On the other hand the thing I really wanted to solve when I > started out was to remove the distinction between mocks and stubs so I'm not > sure it's very bright to introduce the distinction between dummies and > fakes. > > Any thoughts? > > Another related feature is the ability to specify default configurations of > fake objects described here: > http://ondevelopment.blogspot.com/2009/11/configuring-fake-objects-on-global > .html > > > > ------------------------------------ > > Yahoo! Groups Links > |
| Free embeddable forum powered by Nabble | Forum Help |