Home > Blockchain >  How to check if a public method calls another public method using FakeItEasy
How to check if a public method calls another public method using FakeItEasy

Time:11-05

I have the following Interface & Class and I also wrote a unit test as shown down, but I got an exception:

Assertion failed for the following call: AsyncConsole.example1.IPlayer.Start(i: 1) Expected to find it once or more but didn't find it among the calls:

Is there a way to solve that?

public interface IPlayer
{
    public void Play();

    public void Start(int i);
}

public class Player : IPlayer
    {
        public void Play()
        {
            Start(1);
        }

        public void Start(int i)
        {
            Console.WriteLine("Start "   i);
        }
    }

Test class


using FakeItEasy;
using Xunit;

namespace TestProject
{
    public class TestPlayer
    {
        [Fact]
        public void Play_WhenCalled_ShouldCallStart()
        {
            var player = A.Fake<IPlayer>();
            player.Play();

            //assert
            A.CallTo(() => player.Start(1)).MustHaveHappened();
        }
    }
}
Message: 
FakeItEasy.ExpectationException : 

  Assertion failed for the following call:
    AsyncConsole.example1.IPlayer.Start(i: 1)
  Expected to find it once or more but didn't find it among the calls:
    1: IPlayer.Play()

CodePudding user response:

You can't check the calls of the Start method because you expect to IPlayer.Start() call but what actually happened is when you call the Play method of the IPlayer interface, behind the scenes Player.Start(1) calls. In other words interface just a black box and you don't what happened inside. actually, the whole point of Unit testing is that. you have black-box and the only thing you can test are expectations of outputs.

CodePudding user response:

As @Milad Karimifard says, it's unusual to write a test that checks to see if a class calls one of its other methods. Typically you'd be testing the return values of a method, or perhaps that a method called another method on a collaborating object.

One way to do that would be to inject a "console-like" interface into your Player class, and in your test supply a fake one. You could then see if IConsole.WriteLine were called with the expected value.

However, if you're set on continuing to check to see if Player calls its own methods, you need to make a number of adjustments:

  1. Fake Player, not IPlayer. There's no implementation in an interface, so a fake IPlayer will never execute any of the Player code.
  2. Make Player.Start(int) virtual. Otherwise, there's no way for FakeItEasy to intercept the calls and change behaviour.

You'll likely end up with something like this (IPlayer need not change):

public class Player : IPlayer
{
    public void Play()
    {
        Start(1);
    }

    public virtual void Start(int i)
    {
        Console.WriteLine("Start "   i);
    }
}

[Fact]
public void Play_WhenCalled_ShouldCallStart()
{
    var player = A.Fake<Player>();
    player.Play();

    //assert
    A.CallTo(() => player.Start(1)).MustHaveHappened();
}
  • Related