Moq method to call a concrete class

I have a setup like this with a specific class that is being instantiated inside the method that I want to test. I want to mock this particular class so that it doesn't execute code inside. Hence, an exception should not be ruled out:

public class Executor
{
    public bool ExecuteAction(ActionRequest request)
    {
        switch (request.ActionType)
        {
            case ActionType.Foo:
                var a = new Foo();
                return a.Execute(request);
            case ActionType.Bar:
                var b = new Bar();
                return b.Execute(request);
        }

        return true;
    }
}

public class Foo
{
    public virtual bool Execute(ActionRequest request)
    {
        throw new NotImplementedException();
    }
}

public class Bar
{
    public virtual bool Execute(ActionRequest request)
    {
        throw new NotImplementedException();
    }
}

      

My NUnit test looks like this:

[Test]
public void GivenARequestToFooShouldExecuteFoo()
{
    var action = new Mock<Foo>();
    action.Setup(x => x.Execute(It.IsAny<ActionRequest>())).Returns(true);

    var sut = new Mock<Executor>();
    sut.Object.ExecuteAction(new ActionRequest
    {
        ActionType = ActionType.Foo
    });
}

[Test]
public void GivenARequestToBarShouldExecuteBar()
{
    var action = new Mock<Bar>();
    action.Setup(x => x.Execute(It.IsAny<ActionRequest>())).Returns(true);

    var sut = new Mock<Executor>();
    sut.Object.ExecuteAction(new ActionRequest
    {
        ActionType = ActionType.Bar
    });
}

      

I fiddled with CallBase

but it didn't get me anywhere. Anyway, I can easily solve this problem without injecting the dependencies of these classes and adding interfaces? Is this possible using Moq?

The only thing I can do now is move the Execute methods to the Executor class and rename them to ExecuteFoo()

and ExecuteBar()

, but I have a lot of code to move around, so they must be partial classes (subclasses?).

+3


source to share


1 answer


The problem is not mocking the method, but creating a concrete class. Creation Foo

and Bar

must be inverted from Executor

. It is responsible for executing the action, not for creating it. so that this interface was created to handle the creation.

public interface IActionCollection : IDictionary<ActionType, Func<IExecute>> {

}

      

think of it as a set of factories or a set of building strategies.

A common interface was created for actions.

public interface IExecute {
    bool Execute(ActionRequest request);
}

public class Foo : IExecute {
    public virtual bool Execute(ActionRequest request) {
        throw new NotImplementedException();
    }
}

public class Bar : IExecute {
    public virtual bool Execute(ActionRequest request) {
        throw new NotImplementedException();
    }
}

      

And has Executor

been refactored to use Dependency Inversion.

public class Executor {
    readonly IActionCollection factories;

    public Executor(IActionCollection factories) {
        this.factories = factories;
    }

    public bool ExecuteAction(ActionRequest request) {
        if (factories.ContainsKey(request.ActionType)) {
            var action = factories[request.ActionType]();
            return action.Execute(request);
        }
        return false;
    }
}

      



With this refactor, Executor can be tested with fake actions.

public void GivenARequestToFooShouldExecuteFoo() {
    //Arrange
    var expected = true;
    var key = ActionType.Foo;

    var action = new Mock<Foo>();
    action.Setup(x => x.Execute(It.IsAny<ActionRequest>())).Returns(expected);

    var actions = new Mock<IActionCollection>();
    actions.Setup(_ => _[key]).Returns(() => { return () => action.Object; });
    actions.Setup(_ => _.ContainsKey(key)).Returns(true);

    var sut = new Executor(actions.Object);
    var request = new ActionRequest {
        ActionType = ActionType.Foo
    };

    //Act
    var actual = sut.ExecuteAction(request);

    //Assert
    Assert.AreEqual(expected, actual);
}

      

A production implementation of a factory collection might look like this:

public class ActionCollection : Dictionary<ActionType, Func<IExecute>>, IActionCollection {
    public ActionCollection()
        : base() {
    }
}

      

and appropriately tuned to specific types.

var factories = ActionCollection();
factories[ActionType.Foo] = () => new Foo();
factories[ActionType.Bar] = () => new Bar();

      

+3


source







All Articles