mrt181
mrt181

Reputation: 5316

Why does moq not use this parameter in its setup?

I have this test

[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();
}

I get this exception

Moq.MockVerificationException: The following setups were not matched:

ICache m => m.Add(1, )

The invocation contains the second parameter but why does moq not recognize it during setup? It works, when i omit the setup for .Add!?


Update This is the code that is executed

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);
}

Upvotes: 2

Views: 1217

Answers (1)

RandomEngy
RandomEngy

Reputation: 15413

When you use Setup in Moq, you're saying "Return this when you see exactly these parameters". For reference types like Product, it will only work when it sees that exact instance. So when Get runs, it's creating a new Product instance internally and is not matching your expectation from product1.

As Chris mentioned, if you used It.IsAny<Product>() in the Setup instead, it would match the new instance and work as intended.

Upvotes: 5

Related Questions