Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing void method that creates a new object

I have a method like the following:

public void ExecuteSomeCommand()
{
    new MyCommand( someInt, SomeEnum.EnumValue ).Execute();
}

I'd like to test that the enum value that is passed in to the constructor of the ICommand object I'm creating is the correct value. Is there any way I can do this with Rhino.Mocks?

like image 614
alimbada Avatar asked May 11 '11 10:05

alimbada


People also ask

How do you unit test classes which create new objects?

The first step is to import Mockito dependencies into your code. Now let us see an example of how to test the class. Let us assume the below is the class that we want to test. Below is the sample class of the object that is instantiated in ClassToBeTested.

How do you test a void method in unit testing?

Using the verify() method. Whenever we mock a void method we do not expect a return value that is why we can only verify whether that method is being called or not. Features of verify(): Mockito provides us with a verify() method which lets us verify whether the mock void method is being called or not.

Which method is used for unit testing?

Unit Testing Techniques:Black Box Testing - Using which the user interface, input and output are tested. White Box Testing - used to test each one of those functions behaviour is tested. Gray Box Testing - Used to execute tests, risks and assessment methods.


2 Answers

Option 1: Use a Seam

The easiest way is to refactor that method with a seam:

public void ExecuteSomeCommand()
{
    this.CreateCommand(someInt, SomeEnum.EnumValue).Execute();
}

// Your seam
protected virtual ICommand CreateCommand(int someInt, 
    SomeEnum someEnum)
{
    return new MyCommand(someInt, SomeEnum.EnumValue);
}

This way you can intercept the creation of the 'new' operator by extending this class. When doing this by hand, it might look like this:

public FakeSomeService : SomeService
{
    public int SomeInt;
    public SomeEnum SomeEnum;

    protected override Command CreateCommand(int someInt, 
        SomeEnum someEnum)
    {
        this.SomeInt = someInt;
        this.SomeEnum = someEnum;
        return new FakeCommand();
    }

    private sealed class FakeCommand : Command
    {
        public override void Execute() { }
    }
}

This fake class can be used in your test methods.


Option 2: Separate behavior and data

A better way would be to separate the data from the behavior. You command has both data (the message) and the behavior (handling that message). If you are allowed to do such a change in your code base: separate this, for instance by defining commands and command handlers. Here is an example:

// Define an interface for handling commands
public interface IHandler<TCommand>
{
    void Handle(TCommand command);
}

// Define your specific command
public class MyCommand
{
    public int SomeInt;
    public SomeEnum SomeEnum;
}

// Define your handler for that command
public class MyCommandHandler : IHandler<MyCommand>
{
    public void Handle(MyCommand command)
    {
        // here your old execute logic
    }
}

Now you can use dependency injection to inject a handler into the class you wish to test. This class will now look like this:

public class SomeService
{
    private readonly IHandler<MyCommand> handler;

    // Inject a handler here using constructor injection.
    public SomeService(IHandler<MyCommand> handler)
    {
        this.handler = handler;
    }

    public void ExecuteSomeCommand()
    {
        this.handler.Handle(new MyCommand
        {
            SomeInt = someInt,
            SomeEnum = someEnum
        });
    }
}

Since you now separated the data from the behavior, it will be very easy to create a fake command handler (or create it using Rhino mocks) that checks if the correct command was sent to the handler. Manually this would look like this:

public class FakeHandler<TCommand> : IHandler<TCommand>
{
    public TCommand HandledCommand { get; set; }

    public void Handle(TCommand command)
    {
        this.HandledCommand = command;
    }
}

This fake handler can be reused throughout your unit testing project. A test using this FakeHandler could look like this:

[TestMethod]
public void SomeTestMethod()
{
    // Arrange
    int expected = 23;

    var handler = new FakeHandler<MyCommand>();

    var service = new SomeService(handler);

    // Act
    service.ExecuteSomeCommand();

    // Assert
    Assert.AreEqual(expected, handler.HandledCommand.SomeInt);
}

Separating the data from the behavior not only makes your application more testable. It makes your application more resilient to change. For instance, cross-cutting concerns can be added to the execution of commands, without the need to make changes to any handler in the system. Because the IHandler<T> is an interface with a single method, it is very easy to write a decorator that can wrap every handler and add things like logging, audit trailing, profiling, validation, transaction handling, fault tolerance improvents, etc. You can read more about it in this article.

like image 56
Steven Avatar answered Oct 27 '22 15:10

Steven


None that I'm aware of. The closest thing that comes to my mind is to use a factory, then create a StrictMock of that factory. Something like that:

readonly ICommandFactory factory;

public Constructor(ICommandFactory factory)
{
    this.factory = factory;
}
public void ExecuteSomeCommand()
{
    factory.Create( someInt, SomeEnum.EnumValue ).Execute();
}

then, you can place expectations on invokation to Create().

HTH

like image 42
Simone Avatar answered Oct 27 '22 15:10

Simone