0

In an app I'm working in there's a service class(among others) which is used just to call methods on other classes. Recently I've had to work in that area and add another method that does what all the other methods do, call other methods from other classes. Arguably, this whole class shouldn't exist, but that's another topic.

The unit tests that exist for other methods in that class seem to be doing a lot busy work. Going as far as checking the values returned from a mock.

In my eyes this isn't worth writing a unit test for other than confirming that X method is called from Y class. Also known as verify in Java/C#, spy in PHP , called in Python etc.

Here's some pseudo code to get an idea of what I mean

public class SomeClass{
 public void methodA() { ... }
}

public class SomeOtherClass { public String methodB() { ... } }

public class Service { public Service(SomeClass someClass, SomeOtherClass someOtherClass) { ... }

public void doWork() { this.someClass.methodA() this.someOtherClass.methodB() } }

A unit test would look like this

public class UnitTest {
 public void testStuff() {
    SomeClass someClass= mock(SomeClass.class);
    Service service = ...;
verify(someClass).methodA();

} }

Andrei
  • 109
  • 1
    I suppose it does. Reading the top answer seems to agree with what I was thinking: for specific cases such as mine it's fine to check that whatever methods you expect to be called are called. – Andrei Sep 07 '23 at 18:47
  • 1
    I just want to point out that there's nuance here, there's more than one possible correct answer. For example, if the submethod is one for auditing purposes where failing to do so would land the company in legal trouble, that would be a really strong argument for writing the test to confirm that the auditing methods are being called. – Flater Sep 07 '23 at 22:48
  • You don't write tests to confirm a method is called. You write tests to confirm that a result happened. If you're architecture sends results out with a method call then you mock that method call to see what the result was. Not every result comes back in a return. – candied_orange Sep 07 '23 at 22:55
  • @candied_orange i'm a bit confused "you mock that method call to see what the result was", mocking the method call would make it so that you know before hand what the result is. I'm not sure what you mean here. – Andrei Sep 08 '23 at 09:30
  • @Andrei tests of functional code that returns a result are nice and simple. Just check what was returned. However, some code isn’t functional. Some is object oriented. Some code sends messages. And does so by calling a method that lies outside the unit under test. In those cases it makes sense to mock that method to see what the message was. – candied_orange Sep 08 '23 at 10:07
  • That said, refactoring to a testable functional core and an imperative shell free of logic so it doesn’t need testing can greatly simplify testing. – candied_orange Sep 08 '23 at 10:10
  • Yeah that's my point. If you're mocking a method of a class outside the unit test then you must specify the returned result as well, which makes the result pointless. So I see the only worth while test to be simply verifying that said method was called a correct number of times with whatever parameters you'd expect it to have. – Andrei Sep 08 '23 at 10:11
  • @Andrei that would be terrible. What you test is that the expected message would have been sent if not for the mock. If the message is defined as correct only when sent x times with y parameters then your problem isn't testing. Its having an ugly architecture. Testing is only making how ugly that is obvious. Which is a good thing. – candied_orange Sep 08 '23 at 13:08
  • @Andrei you can see an example of refactoring to a testable functional core here. – candied_orange Sep 08 '23 at 13:10
  • Call it "test" instead of "unit test" - then it is much simpler to see if it is important to check this or not. – Thorbjørn Ravn Andersen Sep 10 '23 at 10:43

0 Answers0