Как протестировать метод, который внутренне вызывает метод открытого экземпляра в C#

#c# #.net #xunit #xunit.net

Вопрос:

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

Ниже приведен метод кода

 public class FaxAsEmailBL : FaxEmailBL
{
    private IEmailSender _emailSender;
    private ILogger _log;

    public FaxAsEmailBL(IEmailSender emailSender, ILogger log)
    {
        _emailSender = emailSender;
        _log = log;
    }

    // This method is a part of interface
    public bool SendFaxAsEmail(FaxMailDTO faxMailDTO) 
    {
        bool isEmailSuccessfully = false;

        // performs some validation, it is fine this method is called.
        bool validationCompleted = CompleteValidation(faxMailDTO);
        if (validationCompleted)
        {
            // performs some logic
            faxMailDTO.FromEmailAddress = AppSettingsHelper.FromEmailAddress;

            // this method returns bool I don't want this method to be actually called,
            // neither i can make it virtual or part of interface
            isEmailSuccessfully = 
                SendEmail(AppSettingsHelper.FaxSMTPServer, faxMailDTO);

            if (isEmailSuccessfully)
            {

            }
        }
        return isEmailSuccessfully;
    }
}
 

Ниже приведен мой тестовый код

 [Theory]
[MemberData(nameof(GetFaxAsMailDTO))]
public void SendFaxAsEmailTest_ReturnsTrue(FaxMailDTO faxMailDTO)
{
    string sMTPServerUrl = AppSettingsHelper.RightFaxSMTPServer;

    // this line throws an error System.NotSupportedException:
    // “Unsupported expression: x => x non overridable members"
    _mockNPIFaxAsEmailBL.Setup(x => 
        x.SendEmail(It.IsAny<string>(), It.IsAny<FaxMailDTO>())); 

    var result = _nPIFaxAsEmailBL.SendFaxAsEmail(faxMailDTO);
    Assert.True(result);
}
 

Есть ли какой-либо другой способ проверить этот метод
Спасибо!

Комментарии:

1. Является SendEmail ли частью FaxEmailBL интерфейса?

2. @PeterCsala нет, это не часть FaxEmailBL

3. Дело в том, что вы не должны издеваться над своей сутью. Вы должны издеваться над зависимостями SUT.

Ответ №1:

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

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

Имейте в виду, что методы, связанные с вводом-выводом, трудно поддаются модульному тестированию. Возможно, вы могли бы настроить сервер электронной почты, который получает электронные письма и может каким-то образом сообщить модульному тесту, что он получил электронное письмо. Но это будет изрядный объем работы, и, возможно, не стоит затраченных усилий. Поэтому во многих случаях лучше как можно больше отделять такие методы, как отправка электронных писем, и минимизировать объем логики, которую они содержат. Так что вы можете эффективно протестировать все остальное.