Wednesday 17 August 2022

How to unit test private method in .Net Core application which does not support "PrivateObject"

 Problems:

My application is a .NET Core application.

I have a public method as shown below which has two private methods.

   public bool CallService(JObject requestJsonObj, out Status status)
   {
        bool provisioningSuccess = false;
        var preProcessSuccess = PreProcessing(requestJsonObj,out Status status);
        var postProcessSuccess = PostProcessing(requestJsonObj,out Status status);

        if(preProcessSuccess && postProcessSuccess)
        {
              status = Status.ProvisionSuccess;
              provisioningSuccess = true;
        }
        return provisioningSuccess;
   }

Here is Status and private classes

   public enum Status
   {
       [Description("User/Pwd not valid")]
       CredentialInvalid = 111,
       [Description("Provision is success")]
       ProvisionSuccess = 112,
   }

    private PreProcessing(JObject JosnObj, 
        out Status status)
    {
           using (var client = new HttpClient())
           {
                var request = new {.........};
                var response = client.PostAsJsonAsync("api/preprocess", request).Result;
           }
    }

    private PostProcessing(JObject JosnObj, 
        out Status status)
    {
            //..... 
    }

Tried the below way,

     PrivateObject privateHelperObject = new PrivateObject(typeof(MainService));
     actual = (bool)privateHelperObject.Invoke("CallService", requestJsonObj,status);    

It says

The type or namespace name "PrivateObject" could not be found (are you missing a using directive or an assembly reference?)

This is a .NET CORE project. I am not sure if PrivateObject is supported .net core?



Solution:


You don't need PrivateObject in the first place, as your member to test is public:

var target = new MainService();
var actual = target.CallService(requestJsonObj, status);

That your method itself calls private method doesn't change how you test the public one.

Things get harder if you really need to test the private ones also. So let´s use reflection, which is what PrivateObject does as well under the hood.

var mainServiceObject = new MainService();
var method = mainService.GetType().GetMethod("PreProcessing", BindingFlags.Instance | BindingFlags.NonPublic);

var result = (bool) method.Invoke(mainServiceObject, new[] { requestJsonObj, status });

However be aware that unit-testing private members usually is considered a code smell and often indicates that there are issues with the design - namely that your class is doing too much and should be split into multiple classes each having a single responsibility.




No comments:

Post a Comment