mikeysee
mikeysee

Reputation: 1763

How do I test parent methods?

Suppose I have an interface that looks like this:

interface IMyAPIService
{ 
    List<Order> GetOrders();    
}

And a class that implements it:

class MyAPIService : IMyAPIService
{
    public List<Order> GetOrders() {}
    public bool Login() {}
}

Login calls an external service. I can mock the external service and thus test Login no problem.

GetOrders however must first call Login before it can do what it needs to do.

I want to be able to test that GetOrders also returns an error if Login errors but I cannot mock Login because it is a member of the same class. I could mock the external service that Login calls and make sure it returns error and then I know that Login will return error but im not sure if this is the correct way to do this.

Should I only be testing the interface methods in IMyAPIService and not all the public methods in MyAPIService? How do I test Login then?

Upvotes: 1

Views: 58

Answers (1)

forsvarir
forsvarir

Reputation: 10839

Write tests for the public interface of the class. If there’s no code in your program that would call the Login method on your MyAPIService then there’s no reason for it to be on the public interface of your class.

From your description it should be possible for you to test all of the relevant functionality of the Login method by calling the GetOrders method and mocking the external service.

So you may have some tests like this:

  • TestGetOrdersThrowsWhenExternalLoginFailsWithException
  • TestGetOrdersThrowsWhenExternalLoginFailsWithError
  • TestGetOrdersThrowsWhenExternalProviderHasNoOrders
  • TestGetOrdersReturnsOrdersFromExternalProviderWhenPresent

Your tests should just be another client for your class. As such, they only care about the public interface of the class. From that perspective, it shouldn’t matter if you’ve put the login functionality into a separate private method in your MyAPIService or if you had put all of the login code straight into your GetOrders method. Any tests calling the public GetOrders method should work the same either way.

The point is to test your classes as they will be used by the rest of your production code. If you start making all of your methods public so that you can test them all individually then you tend to end up tightly coupling your tests to your code (making any level of refactoring much more painful than it needs to be), or duplicating tests (GetOrders can’t return any Orders unless the external login has succeeded, so testing that your Login method calls the external login is redundant), or you get into the murky world of mocking the class you’re testing (which can be done with some mocking frameworks). Having more public methods on your class than are needed can also be confusing for other people when they use your class (Hmm…looks like I need to call Login, then I can call GetOrders).

Upvotes: 1

Related Questions