Как выполнить модульное тестирование приватного метода в. Net Базовое приложение, которое не поддерживает «PrivateObject» - PullRequest
0 голосов
/ 10 января 2020

Мое приложение является .NET Core приложением.

У меня есть метод public, как показано ниже, который имеет два закрытых метода.

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

Вот Status и частные классы

   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)
    {
            //..... 
    }

Попробовал приведенным ниже способом,

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

В нем говорится

Не удалось найти имя типа или пространства имен "PrivateObject" (вы пропустили используя директиву или ссылку на сборку?)

Это проект. NET CORE. Я не уверен, поддерживается ли PrivateObject. net core?

Ответы [ 3 ]

3 голосов
/ 10 января 2020

Во-первых, вам не нужно PrivateObject, так как ваш участник для тестирования - public:

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

То, что ваш метод сам вызывает приватный метод, не меняет того, как вы тестируете public one.

Все становится сложнее, если вам действительно нужно проверить и частные. Итак, давайте использовать рефлексию, это то, что PrivateObject делает так же под капотом.

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

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

Однако следует помнить, что закрытые члены юнит-тестирования обычно считаются запахом кода и часто указывают, что есть проблемы с дизайном, а именно то, что ваш класс делает слишком много и должен быть разбит на несколько классов, каждый из которых несет одну ответственность.

2 голосов
/ 10 января 2020
var mainService = new MainService(); // This is only to visualise that you need to pass an instance of the class


var dynMethod = typeof(MainService).GetMethod("PreProcessing", BindingFlags.NonPublic | BindingFlags.Instance);

dynMethod.Invoke(mainService , new object[] { methodParams });

// methodParams должен быть параметрами, которые этот метод принимает

1 голос
/ 10 января 2020

Прежде всего, это редкость, когда вам нужно протестировать приватный метод в unit -tests. Обычно вы тестируете модуль - метод publi c, который вызывает все другие частные (или нет) методы. Но в действительности иногда слишком много логики c внутри частного метода или метода - это обработчики событий / сообщений, которые не вызываются напрямую.

Во-вторых, как уже упоминалось, PrivateObject не является частью. NET Core / Standard, и я думаю, что никогда не будет.

В качестве обходного пути вы можете использовать отражение для вызова приватного метода в своих модульных тестах:

var mainServiceObject = new MainService();
var method = typeof(MainService).GetMethod("PrivateMethod", BindingFlags.Instance | BindingFlags.NonPublic);
var result = method?.Invoke(mainServiceObject, new object[] { requestJsonObj, status });

Ps

Обратите внимание, что в вашем коде CallService это публикуемый c метод, поэтому нет необходимости вызывать его через отражение.

...