views:

29

answers:

1

Hello,

we have a weired problem when using Rhino Mocks and Threads. I've tried to isolate the problem, but now I'm stuck to this:

[TestClass]
public class FoolTests
{
   [TestMethod]
   public void TestMethod_Scenario_Result()
   {
       for (int i = 0; i < 5; i++)
       {
           var fool = MockRepository.GenerateStub<IFool>();
           fool.Stub(x => x.AmIFool).Return(false);
           new Fool(fool);
       }
   }
}

public class Fool
{
   private readonly IFool _fool;
   private readonly Thread _thread;

   public Fool(IFool fool)
   {
       _fool = fool;
       _thread = new Thread(Foolish);
       _thread.Start();
   }

   private void Foolish()
   {
       while (true)
       {
           var foo = _fool.Foolness;
       }
   }
}

public interface IFool
{
   bool AmIFool { get; }
   bool Foolness { get; set; }
}

Nearly all the time when running this test, I get "Test method FoolTests.TestMethod_Scenario_Result threw exception: System.InvalidOperationException: This action is invalid when the mock object is in replay state." on line "fool.Stub(x => x.AmIFool).Return(false);".

I have no idea what should be wrong here. Has anyone an idea or do I have to dig into the Rhino Mocks-code?

A: 

Not sure if this is a complete answer, but this page has an interesting note on multi-threading:

http://www.ayende.com/projects/rhino-mocks/api/files/MockRepository-cs.html

MockRepository is capable of verifying in multiply threads, but recording in multiply threads is not recommended.

First thing I'd try is setting up all mocks and expectations, then executing your constructors. This seems to be working for me:

[TestMethod]
public void TestMethod_Scenario_Result()
{
    var stubs = new IFool[5];
    for (int i = 0; i < stubs.Length; ++i)
    {
        var fool = MockRepository.GenerateStub<IFool>();
        fool.Stub(x => x.AmIFool).Return(false);
        stubs[i] = fool;
    }

    foreach (var stub in stubs)
        new Fool(stub);
}

Since this code works, I imagine the problem is that you are doing playback in one thread while recording (for a different stub) in another thread. Playing back and recording at the same time seems like it isn't thread safe, even if you're operating on different stubs.

Merlyn Morgan-Graham
Thank you for this answer. Probably, I simplified our problem too much. Instead of the for-loop, we have 5+ single tests with the same basic setting which is inside the for-loop. So, if I roll out the for-loop into 5 different tests, your approach isn't working anymore.
Papa Mufflon
We just changed GenerateStub into GenerateMock and voilá, it works now.You pointed us into the right direction, so you get the check ^^
Papa Mufflon