1

I am mocking a function call with two arguments. 1. input immutable class object 2. out parameter.

sample code:

Mock<ISample> mockSample = new Mock<ISample>();

SampleClass MyKey = new SampleClass() { prop1 = 1 };
SampleOutput output = new SampleOutput() { prop2 = 2 };
mockSample.setup(s => s.SampleMethod(It.is<SampleKey>(t => t.Equals(MyKey)), 
out sampleOut))).Returns(true);

in actual code execution this mocked function return proper value if the key is same as mocked key, However, i am seeing a problem that this mocked function is returning same out value even if key does not match.

Any inputs?

Adding key code:

public class Key
{
    public readonly DateTime prop1;
    public readonly string prop2;
    public Key(DateTime prop1, string prop2)
    {
        this.prop1 = prop1;
        this.prop2 = prop2;
    }
    public override bool Equals(object obj)
    {
        if (obj == null)
            return false;

        if (ReferenceEquals(this, obj))
            return true;

        Key other = obj as Key;

        return this.prop1 == other.prop1 && string.Compare(this.prop2, other.prop2);
    }

    public override int GetHashCode()
    {
        return prop1.GetHashCode() ^ prop2.GetHashCode();
    }
}
Jack Sparrow
  • 107
  • 2
  • 8
  • 1
    Possible duplicate of [Assigning out/ref parameters in Moq](https://stackoverflow.com/questions/1068095/assigning-out-ref-parameters-in-moq) – Richardissimo Sep 08 '18 at 04:10
  • 1
    The line `return this.prop1 == other.prop1 && string.Compare(this.prop2, other.prop2);` causes the error `Error CS0019 Operator '&&' cannot be applied to operands of type 'bool' and 'int'` – KozhevnikovDmitry Sep 10 '18 at 06:16
  • Using `.Compare` to check for equality (rather than sorting/ordering) is bad. If the reason is that you want culture-specific comparison (rather than ordinal), you could use `string.Equals(this.prop2, other.prop2, StringComparison.CurrentCulture)`. Of course, if you want ordinal comparison, you would just say `this.prop2 == other.prop2` as usually with strings (there is a specific pre-defined (in C# spec) overload of `operator ==` for that). – Jeppe Stig Nielsen Sep 13 '18 at 09:53

1 Answers1

2

As far as I understood the problem, you need to set up mock on two different behaviors. Please take a look on the example test:

[TestFixture]
public class MoqTests
{
    [Test]
    public void MoqOutParameter()
    {
        // Arrange
        Mock<ISample> mockSample = new Mock<ISample>();

        Key MyKey = new Key(DateTime.Today, "SomeValue");
        SampleOutput sampleOut = new SampleOutput() { prop2 = 2 };

        mockSample.Setup(s => s.SampleMethod(It.Is<Key>(t => t.Equals(MyKey)),
            out sampleOut)).Returns(true);

        // Act  
        SampleOutput out1;
        var result1 = mockSample.Object.SampleMethod(new Key(DateTime.Today, "SomeValue"), out out1);

        SampleOutput out2;
        var result2 = mockSample.Object.SampleMethod(new Key(DateTime.MinValue, "AnotherValue"), out out2);

        // Assert
        Assert.True(result1);
        Assert.AreEqual(out1, sampleOut);

        Assert.False(result2);
        Assert.Null(out2);
    }
}

public class Key
{
    public readonly DateTime prop1;
    public readonly string prop2;

    public Key(DateTime prop1, string prop2)
    {
        this.prop1 = prop1;
        this.prop2 = prop2;
    }
    public override bool Equals(object obj)
    {
        if (obj == null)
            return false;

        if (ReferenceEquals(this, obj))
            return true;

        Key other = obj as Key;

        // was forced to add `== 0` to make it compilable
        return this.prop1 == other.prop1 && string.Compare(this.prop2, other.prop2) == 0;
    }

    public override int GetHashCode()
    {
        return prop1.GetHashCode() ^ prop2.GetHashCode();
    }
}

public class SampleOutput
{
    public int prop2 { get; set; }
}

public interface ISample
{
    bool SampleMethod(Key key, out SampleOutput sampleOut);
}

UPD: I added classes Key, SampleOutput and interface 'ISample', that I used in this example and also sorrounding class of tests. I am using Nunit for launching test, it must not make sence. You can use any unit testing frame work, you want. This example works for me, the test is green. Please try it out and say what differs from your environment. Also note that I have changed the return line in Key.Equals to make it compilable.

Hope it helps.

KozhevnikovDmitry
  • 1,660
  • 12
  • 27