Assert that value has been assigned before method call

455 Views Asked by At

I'm using the AAA-pattern and Rhino mocks for my unit-testing. I want to assert that a specific value (e-mail) has been set on an entity before I call SaveChanges() on DbContext. I have a test-method which looks like this:

protected override void Arrange()
{
    base.Arrange();
    _itemToUpdate = new FooEntity();
}

protected override void Act()
{
    base.Act();
    _resultEntity = Repository.Update(_itemToUpdate);
}

[TestMethod]
public void ShouldAssignEmailBeforeSave() // Act
{
   Context.AssertWasCalled(x => x.SaveChanges(), 
      options => options.WhenCalled(y => 
         Assert.IsTrue(_resultEntity.Email == "somevalue")));
}

But I'm realizing that the "WhenCalled"-method isn't executing, because I've also tried this:

[TestMethod]
public void ShouldAssignEmailBeforeSave()
{
    Context.Expect(x => x.SaveChanges())
       .WhenCalled(y => Assert.IsTrue(false));
}

I have also tried this syntax:

[TestMethod]
public void ShouldAssignEmailBeforeSave()
{
    Context.AssertWasCalled(x => x.SaveChanges(),
       options => options.WhenCalled(z => Assert.IsTrue(false)));
}

Both asserts above passes, which makes it obvious that I'm not using the WhenCalled correctly. Context is a mocked object of my DBSet. I've left the Arrange and the Act outside of the question for now because they seem to do what they should. It's the Assert that's not working.

How do I verify that a property is set on an entity before a method was called? In other words, how do I assert that something happened in a specific order?

  1. Set property.
  2. SaveChanges.

EDIT:

The "error" occurs because the Assert is done after the Act, which is correct. It's not possible to use WhenCalled in the Assert because the Act already happened. In this particular case the WhenCalled will never be invoked since the delegate is created after SaveChanges was invoked and thus didn't exist when called.

The alternative is to use Expect in the Arrange:

protected override void Arrange()
{
    base.Arrange();
    _itemToUpdate = new FooEntity();
    Context.Expect(x => x.SaveChanges()).Return(0).WhenCalled(y =>
    {
        Assert.IsTrue(false);
    });
}

[TestMethod]
public void ShouldCallSaveChanges()
{
    Context.VerifyAllExpectations();
}

But then you have an assert in the Arrange, which I believe goes against best practices of the AAA pattern. Any idéas for a better solution?

2

There are 2 best solutions below

0
On

I ended up with this:

private FooEntity _itemToUpdate;
private FooEntity _resultEntity;

protected override void Arrange()
{
    base.Arrange();
    var correctValue = "somevalue"
    _itemToUpdate = new FooEntity()
    _itemToUpdate.Email = correctValue;

    // Context is a mock of a DbContext and inherited from base class.
    Context.Expect(x => x.SaveChanges()).Return(0).WhenCalled(y =>
    {
        Assert.AreEqual(_resultEntity.Email, correctValue);
    });
    Context.Replay();
}

protected override void Act()
{
    base.Act();
    // Repository is a mock of a repository and inherited from base class.
    _resultEntity = Repository.Update(_itemToUpdate);
}

[TestMethod]
public void ShouldAssignEmailBeforeSave() // Assert
{
   Context.VerifyAllExpectations();
}

Since the entity isn't a mock AssertWasCalled won't work.

1
On

It seems what you're looking for is to verify the order of your mock calls. This was possible was MockRepository.Ordered() method of version 3.5, but is not part of 3.6 syntax.
You can see here and here possible solutions. This one is probably the simplest for AAA:

Context.AssertWasCalled(x => _resultEntity.Email = "somevalue", options => options.WhenCalled(w => Context.AssertWasNotCalled(x=>x.SaveChanges())));
Context.AssertWasCalled(x=>x.SaveChanges());