1
votes

I have this test:

[Test]
public async Task ShouldSortOnAllFormulas()
{

    // Assemble
    const string categoryId = "cameras";
    const string organisationId = "piiick";
    var services = PickContext.GivenServices();
    var pickProvider = services.WhenCreatePickProvider();
    var products = new List<JObject>
    {
        JObject.Parse("{ \"gtin\": \"1\", \"action\": \"No\", \"size\": \"Large\", \"variant\": \"1\" }"),
        JObject.Parse("{ \"gtin\": \"2\", \"action\": \"No\", \"size\": \"Small\", \"variant\": \"1\" }"),
        JObject.Parse("{ \"gtin\": \"3\", \"action\": \"No\", \"size\": \"Small (No Lens)\", \"variant\": \"1\" }")
    };
    var formulas = new List<AnswerFormula>
    {
        new AnswerFormula { Expression = "No", Field = "action", Operator = "=", AnswerId = 170, Filter = true },
        new AnswerFormula { Expression = "Small", Field = "size", Operator = "%", AnswerId = 170, Filter = true },
        new AnswerFormula { Expression = "Small", Field = "size", Operator = "%", AnswerId = 171 }
    };

    services.MockProductProvider.Setup(x => x.ListAvailableMasterProductsAsync(categoryId, organisationId)).ReturnsAsync(products);
    services.MockFilterProvider.Setup(x => x.Filter(products, formulas)).Returns(products);

    // Act
    var uniqueAnswerIds = formulas.Select(m => m.AnswerId).GroupBy(m => m).Select(m => m.First()).ToList();
    await pickProvider.ProcessProductsAsync(formulas, categoryId, organisationId);

    // Assert
    services.MockSortProvider.Verify(x => x.SortAsync(categoryId, products, uniqueAnswerIds));
}

This test fails, but it fails because products is null. The setup, for some reason, is not returning the product list.

In reality, the methods return a new list of products, but I was hoping the setup would be fine like that. I have changed the setup to this:

services.MockProductProvider.Setup(x => x.ListAvailableMasterProductsAsync(categoryId, organisationId)).ReturnsAsync(products.ToList());
services.MockFilterProvider.Setup(x => x.Filter(products, formulas)).Returns(products.ToList());

So they are creating a new product list for each setup, but in my method, the product list is null. Does anyone know why?

This is the method I am testing:

public async Task<IEnumerable<JObject>> ProcessProductsAsync(IEnumerable<AnswerFormula> formulas, string categoryId, string oranisationId)
{
    if (formulas == null) throw new ArgumentNullException(nameof(formulas));

    var listOfFormulas = formulas.Where(m => m.Filter).ToList();
    var answerIds = formulas.Select(m => m.AnswerId).GroupBy(m => m).Select(m => m.First()).ToList(); // Use all formulas, not just filtered
    var products = await _productProvider.ListAvailableMasterProductsAsync(categoryId, oranisationId);

    _scoreProvider.Value.Score(products, listOfFormulas); // Score
    var filteredProducts = _filterProvider.Filter(products, listOfFormulas); // Filter
    var sortedProducts = await _sortProvider.Value.SortAsync(categoryId, filteredProducts, answerIds); // Sort
    _filterProvider.RemoveVariants(sortedProducts); // Remove duplicates

    return sortedProducts;
}
1
Have you tried: services.MockFilterProvider.Setup(x => x.Filter(It.IsAny<List<JObject>>(), It.IsAny<don't know the type())).Returns(products); - Alexandru Clonțea
The problem is the setup for Filter. when exercised, the mock is unable to match the exact objects being used. As suggested by @AlexandruClonțea, you should use the It.IsAny<T>() arguments matchers to loosen the expectations of the mock on that function. You will also encounter the same problem in the verify expression. - Nkosi
changing it to services.MockFilterProvider.Setup(x => x.Filter(It.IsAny<List<JObject>>(), formulas)).Returns(products.ToList()); still returns null :( - r3plica

1 Answers

2
votes

I tried a number of variations and it wasn't the products that were causing the issue. It was the formulas. Not sure why, but changing my test to this:

[Test]
public async Task ShouldSortOnAllFormulas()
{

    // Assemble
    const string categoryId = "cameras";
    const string organisationId = "piiick";
    var services = PickContext.GivenServices();
    var pickProvider = services.WhenCreatePickProvider();
    var products = new List<JObject>
    {
        JObject.Parse("{ \"gtin\": \"1\", \"action\": \"No\", \"size\": \"Large\", \"variant\": \"1\" }"),
        JObject.Parse("{ \"gtin\": \"2\", \"action\": \"No\", \"size\": \"Small\", \"variant\": \"1\" }"),
        JObject.Parse("{ \"gtin\": \"3\", \"action\": \"No\", \"size\": \"Small (No Lens)\", \"variant\": \"1\" }")
    };
    var formulas = new List<AnswerFormula>
    {
        new AnswerFormula { Expression = "No", Field = "action", Operator = "=", AnswerId = 170, Filter = true },
        new AnswerFormula { Expression = "Small", Field = "size", Operator = "%", AnswerId = 170, Filter = true },
        new AnswerFormula { Expression = "Small", Field = "size", Operator = "%", AnswerId = 171 }
    };

    services.MockProductProvider.Setup(x => x.ListAvailableMasterProductsAsync(categoryId, organisationId)).ReturnsAsync(products);
    services.MockFilterProvider.Setup(x => x.Filter(products, It.IsAny<List<AnswerFormula>>())).Returns(products);

    // Act
    var uniqueAnswerIds = formulas.Select(m => m.AnswerId).GroupBy(m => m).Select(m => m.First()).ToList();
    await pickProvider.ProcessProductsAsync(formulas, categoryId, organisationId);

    // Assert
    services.MockSortProvider.Verify(x => x.SortAsync(categoryId, products, uniqueAnswerIds));
}

Works fine.