How can I customize how strings are generated?

Mar 6, 2011 at 1:10 AM
Edited Mar 6, 2011 at 1:14 AM

It seems this should be really easy. Let's say I have a string generator like this

            class MyStringGenerator
            {
                private int stringCounter = 0;
                public string GetString()
                {
                    return "foo" + stringCounter++;
                }
            }

Then I expect

            string s1 = fixture.CreateAnonymous<string>();
            string s2 = fixture.CreateAnonymous<string>();
to return s1="foo1" and s2="foo2".
I was reading the ploeh blog, but it refers to Register method which has been deprecated. 
And I cannot find any documentation on Customize or Customizations. So I did an experiment, and got
fixture.Customizations.Add(new StringSpecimenBuilder1());
to work just fine. But I discovered that I must make StringSpecimenBuilder1() responsible 
for paying attention to the type (string, int, Foo, MyClass, etc...).
Otherwise it returns a specimen for any request. SO that is ok.
But the code to check for the type is a nuisance. So I looked at method Customize<T>. I tried
fixture.Customize<string>(myStringGenerator);
but I don't see the point of the generic parameter. It does not customize only requests for strings,
it also responds to integer requests like
int i1 = fixture.CreateAnonymous<int>(); 
Then I have to check the type requested anyway. So what is the point of Customize<T>? 
And is there a simpler way to make my own string generator?
The SpecimenBuilder is pretty simple except type checking is clumsy.
Or am I doing the simplest things this API can handle?
Coordinator
Mar 6, 2011 at 3:14 AM

The easiest way to get foo1 and foo2 as you describe is to do this:

fixture.Customize<string>(c =>
    c.FromFactory((int i) => "foo" + i));
As a rule of thumb, you don't need to implement ISpecimenBuilder if you just want to customize a particular type, but that interface is handy if you want to introduce behavior that targets many different types.

Mar 6, 2011 at 8:04 PM
Thanks. That works just great! your
c.FromFactory((int i) => "foo" + i));
works great. And also a more customized class of my own works fine too, like this
fixture.Customize<string>(c=>c.FromFactory(() => generator.GetString()));