Arclight
Arclight

Reputation: 483

Verifying set with another mock returns null

Mock Framework: Moq
Test Framework: NUnit

I feel like there's a simple answer to this and I'm just overlooking it, but I can't for the life of me figure out why this is giving me grief.

I have two mocks here, and I'm trying to verify that the unit under test is setting one mock's property to the other mock's property, as such:

[TestFixture]
public class Testmock
{
  protected Mock<IOne> mockOne;
  protected Mock<ITwo> mockTwo;
  protected Controller UnitUnderTest;

  [SetUp]
  public void Setup()
  {
    mockOne = new Mock<IOne>();
    mockTwo = new Mock<ITwo>();
    UnitUnderTest = new Controller(mockOne.Object, mockTwo.Object);
  }

  [Test]
  public void Test1()
  {
    string testString = "test";

    mockOne.SetupGet(o => o.Val).Returns(testString);
    UnitUnderTest.CopyVal();
    mockTwo.VerifySet(t => t.Val = mockOne.Object.Val);
  }
}


public interface IOne
{
  string Val { get; set; }
}

public interface ITwo
{
  string Val { get; set; }
}

public class Controller
{
  IOne one;
  ITwo two;

  public Controller(IOne one, ITwo two)
  {
    this.one = one;
    this.two = two;
  }

  public void CopyVal()
  {
    two.Val = one.Val;
  }
}

When I run this test, it returns an error at VerifySet that says:

Expected invocation on the mock at least once, but was never performed: t => t.Val = (String)null

But underneath that, says:

Performed invocations: ITwo.Val = "test"

So I know for certain that ITwo.Val is getting set with IOne.Val in my Controller, but I must be setting up the mock wrong here for the VerifySet. I can replace the VerifySet with the string directly, e.g.:

mockTwo.VerifySet(t => t.Val = testString);

and the test will pass. Since mockOne.Object.Val is SetupGet to return testString, I don't quite understand why I can't use mockOne.Object.Val in place of testString in the VerifySet.

Upvotes: 0

Views: 357

Answers (1)

Humanier
Humanier

Reputation: 274

I am not sure why mockOne.Object.Val returns null in the context of VerifySet. I believe it has something to do with Moq internal implementation (digging Moq sources can reveal the reason for such behavior).

However I can tell you how to change your test to make it work without using testString variable in VerifySet(). You should use It.Is(x => x == mockOne.Object.Val) instead of referring the mock property directly. Please see below:

[Test]
public void Test1()
{
    string testString = "test";

    mockOne.SetupGet(o => o.Val).Returns(testString);
    UnitUnderTest.CopyVal();
    mockTwo.VerifySet(t => t.Val = It.Is<string>(x => x == mockOne.Object.Val));
}

Hope this helps.

Upvotes: 1

Related Questions