B.Allen
B.Allen

Reputation: 79

What can I do to prevent the method from being called when creating Unit Test?

I want to emphasize that I am fairly new to creating Unit Test but I've been searching far and wide through google and documentation but I can't find a solution or alternative. So currently I am trying to create Unit test for a microservice my team mate and I are working on. The class constructor is structured as follows

 public Constructor(IOptions<AMQ_Config> amqConfig, IConfiguration configuration)
        {
            this.amqConfig = amqConfig.Value;
            this.amqConfig.UserName = configuration["AMQ:UserName"];
            this.amqConfig.Password = configuration["AMQ:Password"];
            //this.errorTypeConfig = errorTypeConfig.Value;
            this.configuration = configuration;
            AMQSubscriber();
        }

When I create a new instance of the constructor in the Unit Test it will always call and iterate through the AMQSubscriber(); method. Naively I just made a duplicate constructor that excludes the method and adds another parameter:

public UnitTestConstructor(IOptions<AMQ_Config> amqConfig, IConfiguration configuration, IConnection connection)
        {
            this.amqConfig = amqConfig.Value;
            this.amqConfig.UserName = configuration["AMQ:UserName"];
            this.amqConfig.Password = configuration["AMQ:Password"];
            //this.errorTypeConfig = errorTypeConfig.Value;
            this.configuration = configuration;
            this.connection = connection;
        }

but this was done for unit testing purposes only. I've read around about how its not a good idea to do this because it defeats the purpose of Unit testing but I can't think how to isolate this since most of the methods require or depend on the parameters: IOptions<AMQ_Config> amqConfig, IConfiguration configuration and our microservice is architectured for Apache NMS AMQ for sending, processing and receiving messages.

Upvotes: 0

Views: 815

Answers (1)

weichch
weichch

Reputation: 10055

You have a few options:

1. Move AMQSubscriber() to another interface

So you will have your constructor look like:

public Constructor(IOptions<AMQ_Config> amqConfig, IConfiguration configuration, IAMQSubscriber subscriber)
{
    // Other code ...
    subscriber.AMQSubscriber();
}

In your unit test, you could either mock IAMQSubscriber using a mocking library, or you could provide a void implementation:

class VoidAMQSubscriberForUnitTest : IAMQSubscriber
{
    public void AMQSubscriber()
    { 
        // Do nothing.
    }
}

For example:

// Real
new YourClass(... , new RealAMQSubscriber());
// Unit test
new YourClass(... , new VoidAMQSubscriberForUnitTest()); 

2. Make internal constructor or static methods:

In this case, only types in the same assembly and the unit test assembly could see those methods. i.e. stop test specific methods being seen publicly.

class YourClass
{
    // Only consumed by unit test
    internal YourClass(IOptions<AMQ_Config> amqConfig, IConfiguration configuration, IConnection connection) 
    { }

    // Only consumed by unit test
    internal static YourClass CreateForUnitTest() { }
}

You might need to add InternalsVisibleToAttribute to your assembly.

Upvotes: 1

Related Questions