Search code examples
entity-frameworkasp.net-core-mvcasp.net-identityxunitfakeiteasy

FakeItEasy class containing fake method not recognized as a fake object problem


I have this code:

[Fact]
public async Task AnnouncerIndex_Test_1()
{
    //Arrange

    var fakeContext = A.Fake<OrganizerDbContext>();
    var fakeUserManager = A.Fake< UserManager<AppUser>>();
    var controller = new AnnouncementsController(fakeContext, fakeUserManager);
    

    A.CallTo(() => controller
                    .IsUserBlockedFromAccesingAnnouncer("aaa"))
                    .Returns(Task.FromResult(false));

    
    //Act
    //some code
     
    //Assert
    //some code

}

I want to run unit tests on methods in my controller, the method I'm testing calls another one and I want to replace value it returns with predefinied one using A.CallTo(()=>). But instead I'm getting informed that tested controller isn't a fake object, after running test I get this summary:

System.ArgumentException : Object 'Organizer3.Controllers.AnnouncementsController' of type Organizer3.Controllers.AnnouncementsController is not recognized as a fake object.

  Stack Trace: 
DefaultFakeManagerAccessor.GetFakeManager(Object proxy) line 28
Fake.GetFakeManager(Object fakedObject) line 28
FakeConfigurationManager.GuardAgainstNonFake(Object target) line 83
FakeConfigurationManager.CallTo[T](Expression`1 callSpecification) line 45
A.CallTo[T](Expression`1 callSpecification) line 161
AnnouncementsControllerTests.AnnouncerIndex_Test_1() line 32
--- End of stack trace from previous location ---

I also tried creating fake controller, but doing so doesn't alow me to test methods inside it.

var fakeController =A.Fake<AnnouncementsController>();           
A.CallTo(() => fakeController
                .IsUserBlockedFromAccesingAnnouncer("aaa"))
                .Returns(Task.FromResult(false));

Test summary:

FakeItEasy.Configuration.FakeConfigurationException : 

  The current proxy generator can not intercept the method Organizer3.Controllers.AnnouncementsController.IsUserBlockedFromAccesingAnnouncer(System.String CUID) for the following reason:
    - Non-virtual members can not be intercepted. Only interface members and virtual, overriding, and abstract members can be intercepted.



  Stack Trace: 
DefaultInterceptionAsserter.AssertThatMethodCanBeInterceptedOnInstance(MethodInfo method, Object callTarget) line 23
FakeConfigurationManager.AssertThatMemberCanBeIntercepted(ParsedCallExpression parsed) line 96
FakeConfigurationManager.CallTo[T](Expression`1 callSpecification) line 46
A.CallTo[T](Expression`1 callSpecification) line 161
AnnouncementsControllerTests.AnnouncerIndex_Test_1() line 36
--- End of stack trace from previous location ---

Solution

  • Your first attempt doesn't work because, as mentioned by the error message, your new AnnouncementsController is not a fake, it's an actual instance of the class, so it can't be configured by FakeItEasy.

    The second attempt (using a fake AnnouncementsController) could work, but you'd need to change IsUserBlockedFromAccesingAnnouncer to make it virtual, so that FakeItEasy can fake it. Also, you would also need to pass the fake dependencies to it, like this:

    var fakeController = A.Fake<AnnouncementsController>(options =>
        options.WithArgumentsForConstructor(() => new AnnouncementsController(fakeContext, fakeUserManager)));