chevron-thin-right chevron-thin-left brand cancel-circle search youtube-icon google-plus-icon linkedin-icon facebook-icon twitter-icon toolbox download check linkedin phone twitter-old google-plus facebook profile-male chat calendar profile-male
0 votes
Hi,

In my application I do certain operations on separate threads.

I believe I have read somewhere on the forum that TypeMock will support multiple threads?

My test method will however not work if the worker is started on a separate thread. The test will just hang.

If I just change the code to let the worker execute on my own thread (with #if DEBUG) the test method will work.

#If DEBUG Then
worker.ThreadProc()
#Else
Dim openThread As New Thread(AddressOf worker.ThreadProc)
openThread.Start()
#End If

Looking forward to your input.

Best Regards

Mats
asked by ramnefors (3.9k points)

5 Answers

0 votes
Hi Mats,

Can you post here the code you are trying to test (or an excerpt of it) and the test you are trying to write? Basically, if the code under test synchronizes between two threads and the test isolates one of the dependencies controlling synchronization, it's the test author's responsibility to substitute the synchronization code. I'd like to see your code to find out if this is the case.

Thanks,
Doron
Typemock Support
answered by doron (17.2k points)
0 votes
Hi Doron,

Sorry for the delay but I got sidetracked on another issue. Here is the information you requested. First the test method:

[TestMethod]
public void InternalFileSaveTest()
{
IMainViewer fakeViewer = Isolate.Fake.Instance<IMainViewer>();
MainController controller = new MainController(fakeViewer);
AssessmentContext context = controller.Context;
Assessment fakeAssessment = Isolate.Fake.Instance<Assessment>();
EditSession session = new EditSession(null, fakeAssessment);
context.Sessions.Add(session);
String file = "SaveFile";

Isolate.WhenCalled(() => fakeAssessment.FileName).WillReturn(file);

controller.InternalFileSave(fakeAssessment);

Isolate.Verify.WasCalledWithAnyArguments(() => fakeViewer.StartProgressBar(null));
Isolate.Verify.WasCalledWithAnyArguments(() => fakeAssessment.Write(file, false));
Isolate.Verify.WasCalledWithAnyArguments(() => fakeViewer.InvokeSaveComplete(null, null));
}

The error message I get when running multi-threaded:

Test method UnitTesting.Main.FileHelpersTest.InternalFileSaveTest threw exception: TypeMock.VerifyException:
TypeMock Verification: Method PvService.Assessment.Write(System.String, Boolean) was expected but was not called.

The code a bit abbreviated:

Public Sub InternalFileSave(ByVal assessment As Assessment)
_viewer.StartProgressBar("Saving")

#If THREADS = "Single" Then
AsyncSave(assessment)
#Else
Dim _saveThread As New Thread(AddressOf AsyncSave)
_saveThread.Start(assessment)
#End If

End Sub

Public Sub AsyncSave(ByVal assessment As Object)
Try
_saveSemaphore.WaitOne()

' Perform the write after having obtained the semaphore
CType(assessment, Assessment).Write(assessment.fileName, False)
Catch ex As Exception
' in the actual code pass exception up to SaveCompleting
Finally
_saveSemaphore.Release()
End Try

' Invoke the save compelete operation on the _viewer thread
_viewer.InvokeSaveComplete(AddressOf SaveCompleting, New Object() {assessment})
End Sub

Public Sub SaveCompleting(ByVal assessment As Assessment)
' Invoked on the GUI thread (viewer) to do final housekeeping
CommandQueue.Instance.Clear()
UpdateMenu()
_viewer.AddMruItem(assessment.FileName)
_viewer.StopProgressBar()
End Sub

There are a total of four test methods failing in a multithreaded run all related to open, saving and autosaving. The code above represents one of these cases.

/Mats
answered by ramnefors (3.9k points)
0 votes
Hi Mats
The problem here is that the verification code at the test method gets called before the methods you want to verify are called.

To solve this you need to synchronize the code under test and the test.
You can create a thread to run controller.InternalFileSave() method than use Thread.Join to make sure the code under test finish before verification

Example:
[TestMethod]
public void InternalFileSaveTest()
{
   IMainViewer fakeViewer = Isolate.Fake.Instance<IMainViewer>();
   MainController controller = new MainController(fakeViewer);
   AssessmentContext context = controller.Context;
   Assessment fakeAssessment = Isolate.Fake.Instance<Assessment>();
   EditSession session = new EditSession(null, fakeAssessment);
   context.Sessions.Add(session);
   String file = "SaveFile";

   Isolate.WhenCalled(() => fakeAssessment.FileName).WillReturn(file);
   controller.InternalFileSave(fakeAssessment);
   
   Thread thread = new Thread(() => controller.InternalFileSave(fakeAssessment));   
   thread.Start();   
   thread.Join();  // Here we wait for the code under test to finish
   
   Isolate.Verify.WasCalledWithAnyArguments(() => fakeViewer.StartProgressBar(null));
   Isolate.Verify.WasCalledWithAnyArguments(() => fakeAssessment.Write(file, false));
   Isolate.Verify.WasCalledWithAnyArguments(() => fakeViewer.InvokeSaveComplete(null, null));
} 


Please let me know if it helps.
answered by ohad (35.4k points)
0 votes
I'm having a smilar problem and run across this thead.

Works:
[TestMethod]
public void ExpectDeviceOpened()
{
    IDevice device = Isolate.Fake.Instance<IDevice>();

    device.Open();

    Isolate.Verify.WasCalledWithAnyArguments(() => device.Open());
}


Does NOT work:
[TestMethod]
public void ExpectDeviceOpened()
{
    IDevice device = Isolate.Fake.Instance<IDevice>();

    var thread = new Thread(param => ((IDevice)param).Open());
    thread.Start(device);
    thread.Join();

    Isolate.Verify.WasCalledWithAnyArguments(() => device.Open());
}
answered by jberd126 (760 points)
0 votes
Hi Jason,

I've run both tests and they passed, this problem was fixed in the upcoming Isolator version (5.3.4) that will be released later this week.

Until the official release I will send you a patch so you can verify that the problem was solved.

Update:
Typemock Isolator 5.3.4 released today (20.8.2009) should solve this issue.
answered by dhelper (11.9k points)
...