IKVMC in Action with Hamcrest

October 11, 2011 | IKVM.NET | Unit Testing

In this post, we saw two possible ways for using code written on a different platform than the one we are working on. Now we will see a scenario where we need to use a Java class library from .NET using the IKVMC tool. We are going to use Hamcrest, a library of matchers for building test expressions.

Before we pass any command line argument to IKVMC we need to detect the dependencies between the jar files. JarAnalyser is a good choice and fortunately there is a tool Jar2ikvmc which uses JarAnalyser to detect dependencies between jar files and then generates command-line script for ikvmc.exe.

The version of Hamcrest that we use is 1.3RC2 and we are going to convert hamcrest-core.jar and hamcrest-library.jar.

Here is the generated script from Jar2ikvmc:

rest-core-1.3.0RC2.jar -target:library
ikvmc hamcrest-library-1.3RC2.jar -target:library -r:hamcrest-core-1.3RC2.dll

Now we can run the generated script on the ikvmc.exe tool. It will generate two .NET assemblies. We can now compare the difference in the syntax with the excellent port NHamcrest by Graham Rhay.

We are going to use the Graham Rhay's Assert class that let us use NHamcrest from xUnit.net.

Here is the code that uses NHamcrest:

public class Assert : Xunit.Assert
{
    public static void That<T>(T actual, IMatcher<T> matcher)
    {
        if (matcher.Matches(actual))
            return;

        var description = new StringDescription();
        matcher.DescribeTo(description);

        var mismatchDescription = new StringDescription();
        matcher.DescribeMismatch(actual, mismatchDescription);

        throw new MatchException(
            description.ToString(),
            mismatchDescription.ToString(),
            null);
    }
}

Here is the code that uses Hamcrest that we coverted using IKVMC:

using org.hamcrest;

public class Assert : Xunit.Assert
{
    public static void That<T>(T actual, Matcher matcher)
    {
        if (matcher.matches(actual))
            return;

        var description = new StringDescription();
        matcher.describeTo(description);

        var mismatchDescription = new StringDescription();
        matcher.describeMismatch(actual, mismatchDescription);

        throw new MatchException(
            description.ToString(),
            mismatchDescription.ToString(),
            null);
    }
}

Here is a unit-test that uses NHamcrest:

using NHamcrest.Xunit
using Xunit;

[Test]
public void Pass()
{
    Assert.That(1, Is.EqualTo(1));
}

Here is a unit-test that uses Hamcrest that we coverted using IKVMC:

using org.hamcrest.core;
using Xunit;

[Fact]
public void EqualTo()
{
    Assert.That(1, IsEqual.equalTo(1));
}

A notable difference is on the different naming conventions (Java methods start with lowercase). However, we can create header interfaces declaring those methods inside.

To sum up, if there is a good quality port we can use the port. In this case, I personally choose to go with NHamcrest. However, we already demoed the alternative approach which also works.