Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AutoMock setup with AutoFixture Data Theories

Ok, as was answered in my other question, AutoMoq does not use AutoFixture by default. That's fine and easily solved by doing a setup and setting ReturnsUsingFixture.

But can that be setup with Auto Fixture Data Theories?

So we have a custom AutoDataAttribute that I'll call [MyAutoData]. And in there we call and set up a bunch of customizations like AutoConfiguredMoqCustomization, configuring it to produce webapi controllers, and registering a lot of custom generators. So we've been able to pull out ALMOST all of the boilerplate configuration into some basic configuration files. We've even set up the MyAutoData attribute for system tests, so if you ask for, say, an Id<Account> it will go and create a new account using the actual webapi calls and return a valid account id.

But how can you handle that for setting up AutoMoq method returns? Here is an example:

    [Theory, MyAutoData]
    public async Task Test(Mock<ICqrsService> mockService, TheRequest request) 
    {
        mockService.Setup(service => service.CreateAsync<TheRequest>(It.IsAny<TheRequest>(), It.IsAny<CancellationToken>()))
        .ReturnsAsync(result); // or similar car with ReturnUsingFixture
        /* now we can test */
    }

In every other case, we've been able to move this kind of configuration into MyAutoData (or into a class it calls). But for AutoMoq I can't see how it should work. We can't do a fixture.

Is there a way to trigger a setup method after AutoFixture generates an item but before it is delivered to the test method? Or is there a way to customize the AutoMoq behavior to just ALWAYS use .ReturnsUsingFixture(fixture)? Or am I just thinking about this problem all wrong?

like image 548
Riplikash Avatar asked Feb 09 '23 18:02

Riplikash


2 Answers

The IPostprocessComposer<T>.Do(Action<T>) method allows you to further customize a specimen after it has been created.

In your case, you could use it inside a customization to setup a generic method on a Test Double to return an object created by AutoFixture:

public class FakeServiceCustomization : ICustomization
{
    public void Customize(IFixture fixture)
    {
        fixture.Customize<Mock<IService>>(composer =>
            composer.Do(fake =>
                fake.Setup(service => service.Create<Something>())
                    .ReturnsUsingFixture(fixture);
    }
}
like image 175
Enrico Campidoglio Avatar answered Feb 11 '23 08:02

Enrico Campidoglio


FWIW, I already think that AutoConfiguredMoqCustomization is too implicit for my tastes. AutoFixture, however, is a community project, and other people found it useful enough to implement it.

I don't think there's any reason that by design AutoConfiguredMoqCustomization doesn't set up generic methods; I think the simple reason is that it's hard to do. In other words, it's not that AutoFixture will not do that for you, but rather that it can't.


All that said, in the spirit of GOOS, I think you should listen to your tests. If the tests are difficult to write, it usually means that the SUT is difficult to use. That ought to first trigger reflection about the SUT, not the tests.

Could you design the SUT so that you don't need this AutoFixture feature?

like image 45
Mark Seemann Avatar answered Feb 11 '23 07:02

Mark Seemann