Muds
Muds

Reputation: 4116

How do I unit test an Action Passed to another method

I am trying to unit test a method which has a line

_pollingService.StartPolling(1000, PollingHit)

Where PollingHit is a private method in calling class and signature of StartPolling is

public void StartPolling(double interval, Action action)

now whatever is inside PollingHit(), how do I test that ? Since responsibility of calling this method is on PollingService, but since that is not a class under test I should not be creating a concrete object of it.

Upvotes: 1

Views: 1433

Answers (1)

Sam Holder
Sam Holder

Reputation: 32964

Test it though the public methods of the class which contains _pollingService based on the desired behaviour of that class. you can test polling service itself by just checking that it calls the passed action, it doesn't matter what that action is.

When you test polling service you should only test that when you start polling it calls the given action at the given interval. Polling service doesn't know anything about PollingHit method (as it is in a different class). To test this you could pass pollingservice a test method which implements a counter and check that the counter is incremented as you would expect. You can (and should) test this without the PollingHit method.

When you come to test the behaviour of the class that is using pollingService, you want to test its behaviour, regardless of how it is implemented. The fact that it uses polling service to call the PollingHit method is an irrelevant implementation detail, what is important is that the behaviour encapsulated by the PollingHit method is invoked when you need it to be.

Imagine if someone comes up with an 'push' based way of doing what you you are currently doing by polling (which is a 'pull' model) and implements a pushNotificationService. The behaviour of the class which uses the polling service should remain the same even after you have refactored it to remove pollingService and replaced it with the new pushNotificationService. If you test the behaviour only then your tests won't need to change after you have made this refactoring change.

If you are already using a mock PollingService then you can probably ditch that and use your own test double and use this to control the invocation yourself. Something like this:

public class TestPollingService : IPollingService 
{ 
    Action theAction; 
    public void StartPolling(double interval, Action action) 
    { 
        theAction = action; 
    } 

    public void TestInvocation() 
    { 
        theAction(); 
    }    
}

Upvotes: 1

Related Questions