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.
public interface ISimpleService
{
int Fizz(int input);
string Buzz(string input);
}
public interface ISimpleServiceFactory
{
ISimpleService Create();
}
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
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...
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?
You don't need a factory nor do you need to setup every method within your interfaces, if I understand correctly you simply want to use Fixture to create a proxy which returns random values for every method you invoke on that proxy. Instead of using AutoMoqCustomization use AutoConfiguredMoqCustomization. It's all in the nuget package called Fixture.AutoMoq.
class Program
{
static void Main(string[] args)
{
}
}
[TestFixture]
public class program
{
[Test]
public void some_test()
{
var fixture = new Fixture();
fixture.Customize(new AutoConfiguredMoqCustomization());
var simpleServices = fixture.CreateMany<ISimpleService>();
foreach (var simpleService in simpleServices)
{
string randomString = simpleService.Buzz("hello");
int randomInt = simpleService.Fizz(15);
}
}
}
public interface ISimpleService
{
int Fizz(int input);
string Buzz(string input);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With