Почему moq не использует этот параметр в своей настройке?

#c# #tdd #mocking #moq

#c# #tdd #издевательство #moq

Вопрос:

У меня есть этот тест

 [Fact]
public void Get_if_item_is_not_in_cache_return_null_returns_true()
{
    var repo = new Repository<IProduct>(
        this.factoryMock.Object, 
        this.cacheMock.Object, 
        this.readerMock.Object, 
        this.storageMock.Object);

    var key = 1;
    const string Name = "Product1";
    var date = new DateTime(0, DateTimeKind.Utc);
    var product1 = this.Product; /* returns new Product(
                                  *     "Product1", 
                                  *     new DateTime(0, DateTimeKind.Utc), 
                                  *     new Dictionary<string, decimal> 
                                  *         { { "@1lom", 0m }, { "@2lom", 0m } })     */

    this.cacheMock.Setup(
        m => m.Add(key, product1)).Returns(product1);
    this.cacheMock.Setup(
        m => m.Get<IList<IDictionary<string, object>>>(0)).Returns(null as IList<IDictionary<string, object>>);
    this.cacheMock.Setup(
        m => m.Get<IProduct>(key)).Returns(null as IProduct);
    this.factoryMock.Setup(
        m => m.Create(
            Name, 
            date, 
            this.cacheMock.Object.Get<IList<IDictionary<string, object>>>(0))).Returns(product1);

    var product2 = repo.Get(key, Name, date);

    Assert.Null(product2);
    this.cacheMock.VerifyAll();
    this.factoryMock.VerifyAll();
}
  

Я получаю это исключение

Исключение Moq.MockVerificationException: следующие настройки не были сопоставлены:

ICache m => m.Добавить(1, )

Вызов содержит второй параметр, но почему moq не распознает его во время настройки? Это работает, когда я опускаю настройку для .Add!?


Обновить Это код, который выполняется

 public virtual T Get(int key, string productName, DateTime date)
{
    return this.Cache.Get<T>(key) ?? this.PersistenStorage.Query(productName, date) ?? this.CreateNewCacheItem(productName, date);
}

protected virtual T CreateNewCacheItem(string productName, DateTime date)
{
    var product = this.Factory.Create(productName, date, this.Cache.Get<IList<IDictionary<string, object>>>(this.RawDataKey));
    return this.Cache.Add(product.GetHashCode(), product);
}
  

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

1. Возможно, вам было бы лучше использовать It. Есть какой-либо <ТИП> вместо явных аргументов

Ответ №1:

Когда вы используете Setup в Moq, вы говорите «Верните это, когда увидите именно эти параметры». Для ссылочных типов, таких как Product , он будет работать только тогда, когда увидит этот точный экземпляр. Итак, когда запускается Get, он создает новый Product экземпляр внутренне и не соответствует вашим ожиданиям от product1 .

Как упоминал Крис, если бы вместо этого вы использовали It.IsAny<Product>() в настройке, он соответствовал бы новому экземпляру и работал по назначению.

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

1. Я попробовал это this.cacheMock. Setup(m => m.Добавить(ключ, Это. IsAny<IProduct>())).Возвращает(product1); но i не работает

2. Вы пробовали отлаживать и выяснять, пытается ли он вызвать Add и с какими параметрами?

3. Да, я отладил код, и он вызывает Add, но затем я увидел вашу фразу «… когда вы видите именно эти параметры». Моя настройка использует 1 в качестве ключа, но реальный код использует product. GetHashCode() в качестве ключа. В этом и заключалась проблема. var key = product1. GetHashCode(); this.cacheMock. Setup(m => m.Добавить(ключ, Это. IsAny<IProduct>())).Возвращает(null как IProduct);