This is a migrated thread and some comments may be shown as answers.

Occurs(n) overrides behavior of Throws()?

1 Answer 13 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
James Legan
Top achievements
Rank 1
James Legan asked on 18 Sep 2012, 08:30 PM
I have a unit test that has two calls to SaveChanges() when the first attempt to call SaveChanges() throws an OptimisticVerificationException, a refresh of the object occurs and then a second attempt is made. When writing my unit test I arranged the following expectations:

Mock.Arrange(() => _mockModel.SaveChanges()).Occurs(2);
 
Mock.Arrange(() => _mockModel.SaveChanges()).Throws<OptimisticVerificationException>(string.Empty).InSequence();
 
Mock.Arrange(() => _mockModel.SaveChanges()).InSequence();
 
Mock.Arrange(() => _mockModel.Users.SingleOrDefault(p => p.Guid == userGuid)).Returns(new User());
 
Mock.Arrange(() => _mockModel.Refresh(RefreshMode.OverwriteChangesFromStore, Arg.IsAny<User>())).MustBeCalled();

What is interesting is that the call to: Mock.Arrange(() => _mockModel.SaveChanges()).Occurs(2); actually breaks the next two lines (the one that throws on the first SaveChanges() in sequence). Regardless of where Occurs(n) appears in the arrange, it breaks the throw. Simply commenting it out allows the test to run as expected.

Am I doing something wrong or is there a defect here?

1 Answer, 1 is accepted

Sort by
0
Ricky
Telerik team
answered on 21 Sep 2012, 07:15 PM
Hi James,

I wrote a simple test to reproduce your problem and found out that if you write it in the following way then it works as expected. Since, you have specified InSequence in the Throws setup, it will make the previous setup first in order. However, by default the behavior is override (similar to other mocking tools). So If you do the following then it will work as expected:

 

Mock.Arrange(() => foo.SaveChanges()).Occurs(2);
Mock.Arrange(() => foo.SaveChanges()).Throws<ArgumentException>();
Mock.Arrange(() => foo.SaveChanges()).InSequence();

Ideally you have to write the test in the following way to cover both the cases:

[TestMethod]
public void ShouldAssertThrowsOnFirstCall()
{
    var foo = Mock.Create<IFoo>();
 
    Mock.Arrange(() => foo.SaveChanges()).Throws<ArgumentException>();
    Mock.Arrange(() => foo.SaveChanges()).InSequence();
 
    try
    {
        foo.SaveChanges();
        Assert.Fail("Must throw an exception");
    }
    catch (ArgumentException ex)
    {
 
    }
 
    foo.SaveChanges();
 
 
    Mock.Assert(() => foo.SaveChanges(), Occurs.Exactly(2));
}
 
public interface IFoo
{
    void SaveChanges();
}


Kind Regards
Mehfuz
the Telerik team

Time to cast your vote for Telerik! Tell DevPro Connections and Windows IT Pro why Telerik is your choice. Telerik is nominated in a total of 25 categories.

Tags
General Discussions
Asked by
James Legan
Top achievements
Rank 1
Answers by
Ricky
Telerik team
Share this question
or