The problem
I have a pretty big application that makes use of a bunch of other services. For testing scenarios I don't want my unit tests to rely on third party systems, so I want to replace the services with fakes or mocks, or whatever.
I've already done most of the hard labor, and replaced the concrete services with a IService
. The concrete Service is wired in with a DI framework
Now I want to replace those with random generated fakes.
The code
Interface of example service:
public interface ISimpleService
{
int Fizz(int input);
string Buzz(string input);
}
Interface of example service factory:
public interface ISimpleServiceFactory
{
ISimpleService Create();
}
Implementation simple as possible
public static void Main(string[] args)
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var service = fixture.Create<ISimpleService>();
var fizzResult = service.Fizz(42);
var buzzResult = service.Buzz("I'd like something random...");
}
This shows what I basically want. I just want autofixture to create some dynamic proxy object for me, with methods that return something random of the type specified in the interface...
Note that I've used AutoMoq here, because by default Fixture doesnt want to create objects from interfaces, but I've tried other frameworks too: FakeItEasy, AutoRhinoMock
Workaround
Implementation that kind of works by manually setting everything
public static void Main(string[] args)
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var serviceMock = fixture.Create<Mock<ISimpleService>>();
// These two lines below cause the magic now
serviceMock.Setup(x => x.Fizz(It.IsAny<int>())).Returns(fixture.Create<int>());
serviceMock.Setup(x => x.Buzz(It.IsAny<string>())).Returns(fixture.Create<string>());
var service = serviceMock.Object;
var fizzResult = service.Fizz(42);
var buzzResult = service.Buzz("I'd like something random...");
}
This does give me the desired result: fizzResult with a random int, buzzResult with a random string (a guid by default) However, this is only a small example, my actual service references are a lot bigger, with up to 100s of methods... (they are external soap services etc, can't help it) I don't want to set up everything manually, if theres a generic solution, that would be great...
An implementation for factories that kind of works by manually setting everything
So, as you might have noticed, I've also posted a ISimpleServiceFactory
interface. This resembles the actual situation, since the actual concrete ISimpleService
requires a bunch of configuration.
So, if we'd use the kind of working solution, we'd come to this:
public static void Main(string[] args)
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var serviceFactoryMock = fixture.Create<Mock<ISimpleServiceFactory>>();
var serviceMockDelegate = new Func<ISimpleService>(() =>
{
var serviceMock = fixture.Create<Mock<ISimpleService>>();
serviceMock.Setup(x => x.Fizz(It.IsAny<int>())).Returns(fixture.Create<int>());
serviceMock.Setup(x => x.Buzz(It.IsAny<string>())).Returns(fixture.Create<string>());
return serviceMock.Object;
});
serviceFactoryMock.Setup(x => x.Create()).Returns(serviceMockDelegate);
var service = serviceFactoryMock.Object.Create();
var fizzResult = service.Fizz(42);
var buzzResult = service.Buzz("I'd like something random...");
}
This seems to be getting a bit of a mess, and this is a pretty small interface. The actual services are many levels deep, with 100s of methods.
For methods in my code that require specific conditions I'll obviously still manually set those conditions, but everything else should be random values by default. Generating large amounts of random objects allows for a bit of fuzzy testing too
Is there a way to automatically generate random objects without all this manual setting up?