Страницы

Поиск по вопросам

пятница, 3 января 2020 г.

Для чего используется Mock.Setup().Verifiable()?

#c_sharp #юнит_тесты #moq


Не могу разобраться для чего используется Mock.Verifiable(), если я правильно понимаю,
такой код:

var mockContainer = new Mock(MockBehavior.Strict, StorageUri);
mockContainer.Setup(c => c.GetBlockBlobReference(It.IsAny()))
             .Returns(mockBlobItem.Object);
// ...
mockContainer.Verify(c => c.GetBlockBlobReference(It.IsAny()), Times.AtLeastOnce);


Будет эквивалентен такому:   

var mockContainer = new Mock(MockBehavior.Strict, StorageUri);
mockContainer.Setup(c => c.GetBlockBlobReference(It.IsAny()))
             .Returns(mockBlobItem.Object)
             .Verifiable();
// ...
mockContainer.Verify();


Есть ещё третий вариант:   

var mockContainer = new Mock(MockBehavior.Strict, StorageUri);
mockContainer.Setup(c => c.GetBlockBlobReference(It.IsAny()))
             .Returns(mockBlobItem.Object);
// ...
mockContainer.Verify(); 


Изучил множество примеров, так вот там используются, как правило, второй или третий
варианты. А ещё есть .VerifyAll().   


Как правильно и почему?
Какие есть особенности и подводные камни?
Как эти варианты зявисят от моделей поведения Strict и Loose?




Не смог найти документацию к Moq (кроме вот этой неполноценной), она вообще есть?
    


Ответы

Ответ 1



Да Вы всё верно поняли. Насколько можно судить из статьи этот метод может быть использован для проверки вызова ранее вызова метода определённого в Setup. var thing = new Thing() { Id = 1 }; var mockMapper = new Mock(); mockMapper.Setup(p => p.Save(thing)).Verifiable(); // do stuff mockMapper.Verify(); Кроме того согласно англоязычного ответа желательно не использовать этот подход т.к. он явно противоречит паттерну AAA. Противоречие заключается в том, что подготовка данных для тестирования (Arrange) и описание того, что должно быть проверено (Assert) происходит в методе Setup. Сами же мейнтейнеры проекта озвучивают ещё рад случаев почему не стоит продолжать развивать такое АПИ Тем не менее этот подход может быть оправдан к примеру необходимостью избежать дублитрования кода. Единственный случай, когда такой подход нельзя будет использовать это при необходимости проверить количество вызовов. В этом случае Вы можете использовать только метод Verify с полным описание ожидаемого вызова: mock.Verify(c => c.Method(It.Is(x => x == "x")), Times.Once); По поводу использования Verify без параметров. Он будет проверять только методы которые Вы в сетапе отметили при помощи метода Verifiable: var mockContainer = new Mock(MockBehavior.Strict, StorageUri); mockContainer.Setup(c => c.GetBlockBlobReference(It.IsAny())) .Returns(mockBlobItem.Object) .Verifiable(); // ... mockContainer.Verify(); Если же вы хотите проверить был ли вызван метод который не был отмечем как Verifiable, можно использовать метод VerifyAll: var mockContainer = new Mock(MockBehavior.Strict, StorageUri); mockContainer.Setup(c => c.GetBlockBlobReference(It.IsAny())) .Returns(mockBlobItem.Object); // ... // Verify - не будет проверять в этом случае // т.к. Вы не получите ошибку даже если метод не был вызван ни разу // для такого случая можно сделать так mockContainer.VerifyAll(); Но лично я бы не использовал VerifyAll хотя-бы потому, что он ну уж совсем не очевиден. Разработка ведётся на гитхабе и кроме детальной документации на которую вы сослались есть быстрый старт и примеры использования.

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

Отправить комментарий