Skip to content

Test using MessageBox by Typemock Isolator

Akira Sugiura edited this page Dec 27, 2014 · 11 revisions

Typemock introduces the sample that replaces MessageBox to a mock in Isolator's Quick Start. Also, you can migrate it to Prig(with Moq).

First, you have to create the indirection settings. Open the Package Manager Console and change Default project: to your test project. Then, execute the following commands:

PM>  pstart -NoIntro
Current Project: IsolatorMigrationDemoTest
WARNING: Change the Current Project from `Default Project: ` on the Package Manager Console if it isn't what you want.


PS IsolatorMigrationDemo> $ReferencedAssemblies | select fullname

FullName
--------
mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Moq, Version=4.2.1409.1722, Culture=neutral, PublicKeyToken=69f491c39445e920
nunit.framework, Version=2.6.3.13283, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77
System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Data.DataSetExtensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
IsolatorMigrationDemo, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null


PS IsolatorMigrationDemo> padd -ra $ReferencedAssemblies[-1]
PS IsolatorMigrationDemo> padd -ra ($ReferencedAssemblies | ? { $_.FullName -match '\.Forms,' })
PS IsolatorMigrationDemo>

Next, get the indirection settings for the method that is used in the sample of Isolator. Execute the following commands to get the information:

PS IsolatorMigrationDemo> $asmInfo = $ReferencedAssemblies[-1]
PS IsolatorMigrationDemo> $asmInfo.GetTypes()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    Form1                                    System.Windows.Forms.Form
False    False    Program                                  System.Object
True     False    SomeClass                                System.Object
True     False    UserOfSomeClass                          System.Object
False    False    Resources                                System.Object
False    False    Settings                                 System.Configuration.ApplicationSettingsBase


PS IsolatorMigrationDemo> $asmInfo.GetTypes() | ? { $_.Name -match 'Class' }

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    SomeClass                                System.Object
True     False    UserOfSomeClass                          System.Object


PS IsolatorMigrationDemo> $asmInfo.GetTypes() | ? { $_.Name -match 'Class' } | pfind

Method
------
Void MyMethod()
Void .ctor()
Void DoSomething()
Void .ctor()


PS IsolatorMigrationDemo> $asmInfo.GetTypes() | ? { $_.Name -match 'Class' } | pfind | pget | clip    # About this resul
ts, paste to IsolatorMigrationDemo.v4.0.30319.v1.0.0.0.prig
PS IsolatorMigrationDemo> $asmInfo = $ReferencedAssemblies | ? { $_.FullName -match '\.Forms,' }
PS IsolatorMigrationDemo> $asmInfo.GetTypes() | ? { $_.Name -eq 'messagebox' }

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    MessageBox                               System.Object


PS IsolatorMigrationDemo> $asmInfo.GetTypes() | ? { $_.Name -eq 'messagebox' } | pfind -m 'show\(system\.string\)'

Method
------
System.Windows.Forms.DialogResult Show(System.String)


PS IsolatorMigrationDemo> $asmInfo.GetTypes() | ? { $_.Name -eq 'messagebox' } | pfind -m 'show\(system\.string\)' | pge
t | clip    # About this results, paste to System.Windows.Forms.v4.0.30319.v4.0.0.0.prig
PS IsolatorMigrationDemo> exit

Go back to Visual Studio, paste each indirection settings to IsolatorMigrationDemo.v4.0.30319.v1.0.0.0.prig and System.Windows.Forms.v4.0.30319.v4.0.0.0.prig. If the build is succeeded, let's migrate the examples!

###Example Test 1 - Simple test using MessageBox Isolator also has powerful feature that replaces any methods by Profiling API. Moreover, as same as JustMock, it has the feature to generate Mock Object. Prig doesn't support it, but it is achieved by combination with Moq.

[Test]
public void MessageBoxShow_should_be_callable_indirectly()
{
    using (new IndirectionsContext())
    {
        // Arrange
        var mockMessageBox = new Mock<IndirectionFunc<string, DialogResult>>();
        mockMessageBox.Setup(_ => _(string.Empty)).Returns(DialogResult.OK);

        PMessageBox.ShowString().Body = mockMessageBox.Object;

        // Act
        MessageBox.Show("This is a message");

        // Assert
        mockMessageBox.Verify(_ => _("This is a message"));
    }
}

Isolate.WhenCalled can be replaced by assigning the Mock Object that is performed setup by Moq.Mock<T>.Setup to the indirection stub of Prig(in this case, PMessageBox.ShowString().Body). Isolate.Verify.WasCalledWithExactArguments is same function as Moq.Mock<T>.Verify. There is no problem. Let's go next!

###Example Test 2 - Complex Test The example is called "Complex" but it is not very difficult :)

[Test]
public void UserOfSomeClassDoSomething_should_show_MessageBox_if_an_exception_is_thrown()
{
    using (new IndirectionsContext())
    {
        // Arrange
        PSomeClass.MyMethod().Body = () => { throw new Exception("foo"); };

        var mockMessageBox = new Mock<IndirectionFunc<string, DialogResult>>();
        mockMessageBox.Setup(_ => _(string.Empty)).Returns(DialogResult.OK);

        PMessageBox.ShowString().Body = mockMessageBox.Object;

        // Act
        var user = new UserOfSomeClass();
        user.DoSomething();

        // Assert
        mockMessageBox.Verify(_ => _("Exception caught: foo"));
    }
}

If there are no special conditions, Isolate.WhenCalled(..).WillThrow can be replaced by assigning the function that is set as throwing an exception directly to the indirection stub of Prig(in this case, PSomeClass.MyMethod().Body). I described earlier about Isolate.WhenCalled(..).WillReturn and Isolate.Verify.WasCalledWithExactArguments, so... Uh, this is everything!

For your information, if the target is complex enough to write the test code though it has any MessageBox processing, I personally think there's a high possibility the design will be failure. It will be allowed against existing codes and legacy codes, but I hope that you don't use the power of darkness like this library against new product codes :)