views:

465

answers:

2

I have a method that looks similar to the following:

public void myMethod(MyClass c)
{
  if (c == null)
  {
    return;
  }
  try
  {
    c.someMethod();
  }
  catch (SomeException e)
  {
    // log the exception, possibly re-throw
  }
}

I am trying to find a way to set up a mock instance of the MyClass parameter c such that it returns a value of null for itself, and that c.someMethod() is never called. My unit test looks like this:

@Test
public void Test_myMethod_With_Null_MyClass_Does_Not_Call_someMethod()
{
    Mockery mockery = new Mockery()
    {{
            setImposteriser(ClassImposteriser.INSTANCE);
    }};

    final MyClass mockMyClass = mockery.mock(MyClass.class);

    try
    {
        mockery.checking(new Expectations()
        {{
            oneOf(mockMyClass).equals(null);
                will(returnValue(true));

            never(mockMyClass).someMethod();
        }});
    }
    catch (Exception e)
    {
        logger.fatal(e);
        fail("Exception thrown in test.");
    }
    Util.myMethod(mockMyClass);
}

Basically, i'm setting up a mock instance of MyClass, and setting the expectations on it that when its value is tested against the null value, it will return true, and that the method someMethod() is never called.

Right now, the test is failing, as jMock says that it's not possible to override methods provided by the Object class (the equals(null) part).

Is there a way to do this with jMock? Does this pattern make sense? Is this a valid test? If not, does anyone have any suggestions on how to test this?

+2  A: 

I do not think you can test this code using only JMock.

I would test this by passing in null directly. If no exceptions are thrown or logged, you know that your code worked as expected.@Test

public void Test_myMethod_With_Null_MyClass_Does_Not_Call_someMethod()
{
    Util.myMethod(null);
    //no exception should be thrown.
}

If you wanted to make it more explicit, you could wrap the myMethod(null) call in a try/catch block, but that is not necessary except to clarify the failure reason when there is a failure.

public void Test_myMethod_With_Null_MyClass_Does_Not_Call_someMethod()
{
    try
    {
        Util.myMethod(null);
    }
    catch( ExpectedException e )
    {
        fail( "Should not have thrown exception: " + e.getMessage() ); 
    }
}

This is a sufficient test because you know that if c is null then c.something() of course cannot be called.

Alex B
I suppose this is really the only way to test it - passing in a null, that is. Just checking if there's an actual way to do it w/ mocks. Cheers!
mjd79
+1  A: 

Mocks are supposed to be used to test how an object interacts with its collaborators. If there is no collaborator, then there's nothing to mock. Passing in a null is simpler and more expressive.

Steve Freeman