1

I have similar problem to the one asked here or here but the solutions seems not apply in my case.

Consider the following classes:

public interface IProductsWebService
{
    ICObjectLang[] GetClassLevel(getClassLevelLang criteria);
}

// the rest of this class was automaticaly generated as web service reference
public partial class getClassLevelLang : IEquatable<getClassLevelLang>
{
    public override bool Equals(object obj)
    {
        var other = obj as getClassLevelLang;

        return Equals(other);
    }

    public bool Equals(getClassLevelLang other)
    {
        if (this == other)
        {
            return true;
        }

        if (other == null)
        {
            return false;
        }

        return CID == other.CID &&
               accessCode == other.accessCode &&
               classCode == other.classCode &&
               depth == other.depth &&
               language == other.language &&
               partyCode == other.partyCode &&
               refId == other.refId;
    }

    public override int GetHashCode()
    {
        var hash = 531;

        hash += CID != null ? CID.GetHashCode() : 1;
        hash += accessCode != null ? accessCode.GetHashCode() : 1;
        hash += classCode != null ? classCode.GetHashCode() : 1;
        hash += depth != null ? depth.GetHashCode() : 1;
        hash += language != null ? language.GetHashCode() : 1;
        hash += partyCode != null ? partyCode.GetHashCode() : 1;
        hash += refId != null ? refId.GetHashCode() : 1;

        return hash;
    }

    public override string ToString()
    {
        var str = new StringBuilder();

        str.AppendFormat("CID: {0}, ", CID);
        str.AppendFormat("accessCode: {0}, ", accessCode);
        str.AppendFormat("classCode: {0}, ", classCode);
        str.AppendFormat("depth: {0}, ", depth);
        str.AppendFormat("language: {0}, ", language);
        str.AppendFormat("partyCode: {0}, ", partyCode);
        str.AppendFormat("refId: {0}", refId);

        return str.ToString();
    }
}

And the following code for testing (calls list is only for debugging):

private Mock<IProductsWebService> productsService;
private IProductsImportProcess target;

private List<getClassLevelLang> calls = new List<getClassLevelLang>();

[TestMethod]
public void RecursiveDownloadTest()
{
        //other mocks (configuration, log, categoryService and configurationService) set here

        target = new ProductsImportProcess(
            configuration.Object, log.Object, categoryService.Object,
            productsService.Object, configurationService.Object);

        productsService = new Mock<IProductsWebService>(MockBehavior.Strict);

        var root1 = new Category
        {
            CategoryID = "root1",
            SubCategories = new List<Category>
                                                {
                                                    new Category
                                                        {
                                                            CategoryID = "cat1.1",
                                                            SubCategories = new List<Category>
                                                                                {
                                                                                    new Category
                                                                                        {CategoryID = "cat1.1.1"}
                                                                                }
                                                        },
                                                    new Category
                                                        {
                                                            CategoryID = "cat1.2"
                                                        }
                                                }
        };
        var root2 = new Category { CategoryID = "root2" };

        setupProductsServiceCall("tree1", root1, true);
        setupProductsServiceCall("tree1", root1.SubCategories.First().SubCategories.First());
        setupProductsServiceCall("tree2", root2, true);

        target.Execute();

        productsService.VerifyAll();
    }

    private void setupProductsServiceCall(string treeCode, Category category, bool isRoot = false)
    {
        var config = configuration.Object;

        var criteria = new getClassLevelLang
                           {
                               CID = isRoot ? null : category.CategoryID,
                               language = "all",
                               partyCode = "something",
                               depth = "1",
                               classCode = treeCode,
                               accessCode = "xyz"
                           };
        var productsNode = TestUtils.CreateAbbProductsNode(category);

        productsService.Setup(mock => mock.GetClassLevel(It.Is<getClassLevelLang>(c => c.Equals(criteria)))).
            Callback<getClassLevelLang>(c => calls.Add(c)).        //added for debuging purposes only
            Returns(productsNode.objectAttributes).
            Verifiable();
}

The test above fails with the following exception:

Test method ProductsImport.Console.Test.ProductsImportProcessUnitTest.RecursiveDownloadTest threw exception: 
Moq.MockVerificationException: The following setups were not matched:
    IProductsWebService mock => mock.GetClassLevel(It.Is<getClassLevelLang>(c => c.Equals(CID: , accessCode: xyz, classCode: tree1, depth: 1, language: all, partyCode: something, refId: )))
    IProductsWebService mock => mock.GetClassLevel(It.Is<getClassLevelLang>(c => c.Equals(CID: cat1.1.1, accessCode: xyz, classCode: tree1, depth: 1, language: all, partyCode: something, refId: )))
    IProductsWebService mock => mock.GetClassLevel(It.Is<getClassLevelLang>(c => c.Equals(CID: , accessCode: xyz, classCode: tree2, depth: 1, language: all, partyCode: something, refId: )))
Result StackTrace:    
    at Moq.Mock.VerifyAll()

I'm sure that ProductsWebService.GetClassLevel is being called while getClassLevelLang.Equals is not (checked with debugger). What's more weird I've checked the actual value of calls just before calling VerifyAll() list and it's empty.

Community
  • 1
  • 1
Marek
  • 1,688
  • 1
  • 29
  • 47

1 Answers1

1

Your productsService mock is not getting injected into your ProductsImportProcess so cannot intercept calls made on the actual IProductsWebService. How do you instantiate the IProductsWebService object in your code?

levelnis
  • 7,665
  • 6
  • 37
  • 61
  • Actually it is injected in code above - by constructor: `target = new ProductsImportProcess(..., productsService.Object, ...);` In my application its injected by IoC container (Ninject) – Marek Mar 04 '13 at 13:19
  • OK, but then, according to the code above, you instantiate it AFTER you inject it, so when it's injected into your test, it's going to be null – levelnis Mar 04 '13 at 14:51
  • Yes, you've got the point - I've was changing the code so many times after receiving the first such error (before implementing the custom equality logic in `getClassLevelLang`) that I've missed that. Rookie mistake... Thx a lot! – Marek Mar 05 '13 at 06:48