Имитирующий унаследованный класс с Moq

#c# #inheritance #methods #moq

#c# #наследование #методы #moq

Вопрос:

У меня есть несколько методов веб-API, для которых я хочу написать модульные тесты. Им нужен доступ к базе данных, поэтому, естественно, я хотел уточнить эту часть.

Доступ к классам хранилища осуществляется через интерфейс, и класс, реализующий метод API, наследует интерфейс. Чего я не знаю, так это как издеваться над унаследованным интерфейсом в модульном тестировании.

 public class CreateWishList : APIAccess
{
    public long CreateWishListV1(long userId, string wishListName)
    {
        // Do stuff like
        long result = Storage.CreateWishList(userId, wishListName);

        return resu<
    }
}

public class APIAccess
{
    protected IStorage Storage { get; private set; }

    public APIAccess() : this(new APIStorage()) { }

    public APIAccess(IStorage storage)
    {
        Storage = storage;
    }
}

public interface IStorage
{
    long CreateWishList(long userId, string wishListName);
}
  

Итак, я хочу провести модульное тестирование CreateWishListV1(...) метода, и чтобы сделать это без доступа к базе данных, мне нужно смоделировать то, что Storage.CreateWishList(...) возвращает. Как мне это сделать?

Обновить:

Я пытаюсь что-то вроде этого:

 [Test]
public void CreateWishListTest()
{
    var mockAccess = new Mock<APIAccess>(MockBehavior.Strict);
    mockAccess.Setup(m => m.Device.CreateWishList(It.IsAny<long>(), It.IsAny<string>())).Returns(123);

    var method = new CreateWishList();
    method.Storage = mockAccess.Object;

    long response = method.CreateWishListV1(12345, "test");

    Assert.IsTrue(response == 123, "WishList wasn't created.");
}
  

Также пришлось изменить Storage свойство APIAccess на public.

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

1. Что именно вы пытаетесь протестировать? Почему вы вызываете CreateWishListV1 в макете? Я думаю, что это метод, который вы хотите протестировать?

2. Да, я делал это неправильно. Обновил вопрос; это лучше?

Ответ №1:

У меня в голове не укладывается:

 var storage = new Mock<IStorage>();
storage.Setup(x => x.CreateWishList(It.IsAny<long>(), It.IsAny<string>())
       .Returns(10);
  

Затем создайте свой CreateWishList объект с его собственным конструктором, принимающим IStorage .

 var createWishList = new CreateWishList(storage.Object);  
  

Для модульного тестирования вашего CreateWishList() метода вам следует написать отдельный тест. Этот тест должен проводиться исключительно для проверки кода в CreateWishListV1() .

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

1. Есть ли способ сделать это без создания конструктора?

2. Вы могли бы сделать Storage свойство общедоступным, чтобы модульный тест мог его установить. В любом случае — вы не можете ожидать, что модульный тест назначит зависимость, когда вы создаете экземпляр зависимости внутри объекта.

3. Да, вы могли бы внедрить хранилище с помощью свойства или задать его с помощью отражения. Но создание конструктора, который принимает хранилище, было бы самым чистым способом, ИМХО.