Reputation: 1763
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
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:
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