Home Mocking adding items to a list in .NET NMock2
Reply: 1

Mocking adding items to a list in .NET NMock2

Peete
1#
Peete Published in 2017-12-08 01:08:51Z

I'm using NMock2 (2.1.3641.27570) in my unit tests.

IList<MyObj> values = _mock.NewMock<IList<MyObj>>();

That mock I return when my tested object calls the Values get property on my mocked object:

Expect.AtLeastOnce.On(_myKeepMock).GetProperty("Values").Will(Return.Value(values));

Then I expect value which is a MyObj to be added to my list values:

Expect.AtLeastOnce.On(values).Method("Add").With(value);

In order to avoid unexpected invocation of list'1.Add upon execution I understand I have to override the Equals method in the MyObj class:

public override bool Equals(object obj) { ...}

and compare by value instead of reference. But it doesn't even get called when executing the test (breakpoint not hit).

What do I need to do in order to pass the test when the item added to the list in the call is equal in value to the one added by the tested object?

I read about custom matchers but not sure if those apply here.

UPDATE

Full example:

using System.Collections.Generic;
using System.Linq;
using NMock2;
using NUnit.Framework;

public class Data
{
    public int Val { get; set; }

    public Data(int val) { Val = val; }


}
public class ModData
{
    public int Val { get; set; }


    protected bool Equals(ModData other)
    {
        return this.Val.Equals(other.Val);
    }

    public override int GetHashCode()
    {
        return this.Val.GetHashCode();
    }

    public override bool Equals(object obj)
    {
        ModData m = (ModData)obj;

        return m != null && this.Val == m.Val;
    }

}


public interface IAllData
{
    IList<Data> Data { get; set; }
    IList<ModData> ModData { get; set; }
}

public class AllData : IAllData
{
    public IList<Data> Data { get; set; }
    public IList<ModData> ModData { get; set; }


}

public class Calco
{
    private IAllData _allData;

    public Calco(IAllData allData)
    {
        _allData = allData;
    }

    public void Sum()
    {
        _allData.ModData.Add(new ModData { Val = _allData.Data.Sum(d => d.Val) });
    }
}





public class CalcoTest
{
    [Test]
    public void Test()
    {
        Mockery mockery = new Mockery();
        IList<Data> data = new List<Data>();
        IList<ModData> modData = mockery.NewMock<IList<ModData>>();
        IAllData allData = mockery.NewMock<IAllData>();

        ModData modDatum = new ModData { Val = 4 };

        data.Add(new Data(1));
        data.Add(new Data(10));

        Calco c = new Calco(allData);



        Expect.AtLeastOnce.On(allData).GetProperty("Data").Will(Return.Value(data));
        Expect.AtLeastOnce.On(allData).GetProperty("ModData").Will(Return.Value(modData));
        Expect.AtLeastOnce.On(modData).Method("Add").With(modDatum);

        c.Sum();

        mockery.VerifyAllExpectationsHaveBeenMet();

    }
}

Output:

NMock2.Internal.ExpectationException : unexpected invocation of list`1.Add(<WRM.Common.RiskCalculation.Tests.ModData>)
Expected:   
  at least 1 time: allData.Data, will return <System.Collections.Generic.List`1[WRM.Common.RiskCalculation.Tests.Data]> [called 1 time]
  at least 1 time: allData.ModData, will return <list`1> [called 1 time]
  at least 1 time: list`1.Add(equal to <WRM.Common.RiskCalculation.Tests.ModData>) [called 0 times]

Notice how it expects invocation of list'1.Add(<WRM.Common.RiskCalculation.Tests.ModData>) and then shows it didn't call list'1.Add(<WRM.Common.RiskCalculation.Tests.ModData>)

Peete
2#
Peete Reply to 2017-12-08 02:54:31Z

Custom Matchers ARE the answer: http://nmock.sourceforge.net/advanced.html

public class IsMod
{
    public static Matcher Equal(ModData otherMod)
    {
        return new ModMatcher(otherMod);
    }
}

internal class ModMatcher : Matcher
{
    private readonly ModData _mod;

    public ModMatcher(ModData mod)
    {
        _mod = mod;
    }

    public override bool Matches(object o)
    {

        ModData m = (ModData)o;
        return _mod.Val.Equals(m.Val);
    }

    public override void DescribeTo(TextWriter writer)
    {
        writer.Write("Value same ");
        writer.Write(_mod.Val);
    }
}

And then

Expect.AtLeastOnce.On(modData).Method("Add").With(IsMod.Equal(modDatum));

Done!

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.301693 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO