2
votes

I have achieved a solution to mock test the public virtual method using FakeItEasy Framework. Below I have a Test class with Private method and private method cannot be virtual. So please help me t mock the Private method using FakeItEasy Framework

Class To be tested

public class XYZ
{
    public static int nValue = 0;

    private  void AddInetegers()
    {
        int i = 3;

        int j = i * 100;
        int k = j * 30 / 100;

        Show(String.Format("Value Here {0}", k.ToString()));

        nValue = k;
    }

    public virtual void Show(string message)
    {
        MessageBox.Show(message);
    }
}

Test Class

[TestMethod]
   public void Test_Using_FakeItEasy()
    {

        var instance = A.Fake<XYZ>();

        A.CallTo(() => instance.Show("Hello"));

        //A.CallTo(() => instance.AddInetegers(3)).CallsBaseMethod();

        A.CallTo(instance).Where(x => x.Method.Name.Contains("AddInetegers")).MustHaveHappened();


        Assert.AreEqual(90, XYZ.nValue);
    }

Error:

Result Message: Test method PrjMSTest.Test.Test_Using_FakeItEasy threw exception: FakeItEasy.ExpectationException:

Assertion failed for the following call:
Any call made to the fake object.
where x => x.Method.Name.Contains("AddInetegers")
Expected to find it at least once but no calls were made to the fake object.

1
Simply - you cannot mock private methods (unless you are using commercial mocking frameworks). You never need to test private methods, because private methods will be always called through public methods - so testing public methods you will test private as wellFabio
FakeItEasy is commercial mocking frameworks??Sujeet Singh
you never need to mock private methods.Fabio
@andreasnico This question is related to Mocking Private Method, Other question was for Partial Mocking. only the thing is I have used same sample code. How it can be duplicate?Sujeet Singh
@FrancescoB. I achived using the PrivateObject class, for reference you can go to the link stackoverflow.com/questions/5396996/…Sujeet Singh

1 Answers

1
votes

As they told you in the comments, you can't easily test private methods and, in the vast majority of cases, probably you shouldn't.
If, for some reason, you still want to test AddInetegers(), there's a "dirty" way to keep some kind of information hiding and to test your method.

First, you have to make AddInetegers internal; it won't be visible outside your assembly and you will be able to test it.

Then find the Properties\AssemblyInfo.cs file of the project to which your XYZ class belongs to; supposing your project is named MyProject and your test project is MyProjectTests, you can add

using System.Runtime.CompilerServices;

to the top of AssemblyInfo.cs and

[assembly: InternalsVisibleTo("MyProjectTests")]

to the bottom. This will make your method testable. More info here or here.


hereherePrivateObjectthis article
var CurrentInstance = new XYZ();
var PrivateObject= new PrivateObject(CurrentInstance);
PrivateObject.Invoke("AddInetegers");

Assert.AreEqual(90, XYZ.nValue);


This answer
  1. When refactoring and/or adding tests to a legacy system that perhaps you still haven't had the time to get acquainted with

sometimes it is simply safest to just test the private functionality

  1. When someone gave you an unreasonable deadline

You're in a rush, and have to do the fastest thing possible for here and now. In the long run, you don't want to test private methods. But I will say that it usually takes some time to refactor to address design issues. And sometimes you have to ship in a week. That's okay: do the quick and dirty and test the private methods using a groping tool if that's what you think is the fastest and most reliable way to get the job done. But understand that what you did was suboptimal in the long run, and please consider coming back to it (or, if it was forgotten about but you see it later, fix it).