Make sure the call was not made using any generic parameters using FakeItEasy

Disclaimer is not a question that How to use FakeItEasy to assert a method is not being called

Explanation

I have a piece of code that registers the contents of an IOC container, and I can use FakeItEasy in my tests to ensure registration.

I am trying to figure out how to ensure that unexpected calls are not made.

Quick repo (problem boils down to multiple test classes - this is not a real implementation)

public class Foo
{
    private readonly ICustomContainer m_CustomContainer;

    public Foo(ICustomContainer customContainer)
    {
        m_CustomContainer = customContainer;
    }

    public void Bar()
    {
        m_CustomContainer.Register<IMyInterface, IMyImplementation>();
    }
}

public interface ICustomContainer
{
    void Register<TInterface, TImplementation>() where TImplementation : TInterface;
}

public class UnitTest1
{
    [Fact]
    public void Test1()
    {
        //Arrange
        ICustomContainer fake = A.Fake<ICustomContainer>();
        Foo objectUnderTest = new Foo(fake);

        //Act
        objectUnderTest.Bar();

        //Assert
        A.CallTo(() => fake.Register<IMyInterface, IMyImplementation>()).MustHaveHappened();
        //A.CallTo(() => fake.Register<???>()).MustNotHaveHappened();  //Any generic parameter apart from <IMyInterface, IMyImplementation> must not have happened
    }
}

      

The above test will pass - that's right. If in the future I had to add another registration to Bar()

, it will still pass - which is not as good as my test only tests known scenarios.

What I am trying to achieve

So, given the interface defined above for ICustomContainer

which is my IOC container, I would like to make sure that it is only called as expected.

What I have already researched

There have been other mocking frameworks used in the past like the TypeMock Isolator, I could set a fake object to throw exceptions if no specific (expected) calls were made. I don't know if I can do this with FakeItEasy. Also, the TypeMock Isolator doesn't support .NET Core, so it doesn't feel good to me.

If I had a method that didn't use a shared parameter, I could get FakeItEasy to count the number of times the method was called and expect it to be called with any arguments in addition to testing the expected calls. This is definitely an option, but it means I need to create a facade over my interface (like an extension method or wrapper) in order to accept type parameters and not general parameters, which means I'm wasting my pre-compilation time warning i I get with a general parameter constraint.

Actual question

How do I modify my test so that I can assert that the unexpected call was not made using any generic parameters other than what I expected using .NET Core / FakeItEasy / xUnit?

+3


source to share


1 answer


I can simplify, but it sounds like Strict Fake can help you. Do one thing and then explicitly allow whatever calls you want.



//Arrange
ICustomContainer fake = A.Fake<ICustomContainer>(x => x.Strict());

// allow just the registrations you want to
A.CallTo(() => fake.Register<IMyInterface, IMyImplementation>()).DoesNothing();

Foo objectUnderTest = new Foo(fake);

//Act
objectUnderTest.Bar();

//Assert
A.CallTo(() => fake.Register<IMyInterface, IMyImplementation>()).MustHaveHappened();

      

+3


source







All Articles