Как написать модульный тест для метода Controller с двумя параметрами и какие сценарии требуются для тестирования? - PullRequest
0 голосов
/ 10 мая 2018

Я новичок в модульном тестировании.Я хотел бы написать модульные тесты для действия удаления контроллера.Я хочу использовать NSubstitute, чтобы высмеивать все зависимости.Текущая реализация использует интерфейс IRepository для абстрагирования вызовов к базовому источнику данных.

Контроллер

public ActionResult Delete(string fileName, bool isPublic)
{
    try
    {
        repo.DeleteDocument(new PortalDocument
        {
            Path = fileName,
            IsPublic = isPublic
        });
    }
    catch (Exception e)
    {
        EventLog.Logger.LogCritical(e, e.Message);            
    }
    return RedirectToAction(IndexViewName);
}

Интерфейс для хранилища.

public interface IRepository<out T> where T: 
    CloudBlobContainer
{
    bool DeleteDocument(PortalDocument document);
}

PortalDocument Class

public class PortalDocument
{
    public bool IsPublic { get; set; }
}

Заранее спасибо.

1 Ответ

0 голосов
/ 11 мая 2018

Я думаю, что вы выяснили сценарий счастливого пути, тестирования того, что происходит, когда нет исключения. Но теперь вам нужно проверить несчастный путь, он ведет себя правильно, когда выдается исключение.

//arrange
var mockRepo = new Mock<DocumentRepository>(MockBehavior.Strict);
mockRepo.Setup(r => r.DeleteDocument(It.IsAny<PortalDocument>())).Throws(new Exception("test"));

var controller = new DocumentController(mockRepo.Object);

//act
var result = controller.Delete("filename", true);


//assert
//make sure result is a redirect result
//but how do I test that it got logged?

К сожалению, вы обнаружите, что не можете на самом деле проверить, что вы что-то записали. Зачем? Потому что у вас есть статический вызов метода. Вызовы статических методов не тестируются. Вместо этого вы должны следовать принципу инверсии зависимостей .

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

public interface ILogger
{
    void LogCritical(Exception exception);
}

public class EventLogLogger : ILogger
{
    public void LogCritical(Exception exception)
    {
        EventLog.Logger.LogCritical(exception, exception.Message); 
    }
}

Тогда ваш юнит-тест становится:

//arrange
var mockRepo = new Mock<IDocumentRepository>(MockBehavior.Strict);
mockRepo.Setup(r => r.DeleteDocument(It.IsAny<PortalDocument>())).Throws(new Exception("test"));

var mockLogger = new Mock<ILogger>(MockBehavior.Strict);
mockLogger.Setup(l => l.LogCritical(It.IsAny<Exception>())).Verifiable;

var controller = new DocumentController(mockRepo.Object, mockLogger.Object);

//act
var result = controller.Delete("filename", true);


//assert
//make sure result is a redirect result
mockLogger.Verify();

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

Если вы новичок в внедрении зависимостей, я настоятельно рекомендую посмотреть Miguel Castro .

.
...