0

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()
1
  • Please note that I don't want to use 'virtual' instead of 'public' for Start method. Commented Nov 4, 2022 at 2:33

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

1 Comment

So, what I should change/modify to check the call? My goal is to check if Start(1) is being called by Play(). Any Idea?
1

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();
}

8 Comments

Thanks for the answer, but why it works for virtual and not for public? any reason for that?
FakeItEasy uses CastleDynamicProxy to essentially create a class that inherits from the interface or class that is faked, and implements derived methods in a way that makes them interceptable and configurable. Non-virtual members can't be reimplemented. fakeiteasy.readthedocs.io/en/stable/what-can-be-faked/… . You can simulate by creating your own "FakePlay" class that derives from Play.
@MikeBluer virtual and public are not mutually exclusive; the method can be both public and virtual.
@ThomasLevesque But why it works if I check a public method from another Class. What I mean, it will work if I check the call of another class, and not working if I check the call of a public method in the same class!! WHY?
@MikeBluer, I did test it. And just now again, copying from my answer above and pasting in my local editor. It passed. From your error, can not intercept the method Player.Start(), I suspect you've changed something, since there's no parameterless Start listed in either your question or my answer.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.