1

I'm trying to write a unit test for an implementation of a Feign client. I wasn't sure how to go about it so I googled it and came across this answer and the accepted answer is this code snippet:

@Test
public someTestClient(){
    Person expectedPerson = new Person("name",12));
    when(mockPersonClient.getPerson()).return(expectedPerson);
    Person person = mockPersionClient.getPerson();
    assertEquals(expectedPerson, person);
}

I don't understand why this is a useful test or under what circumstance, other than a problem with the Person constructor, this test could ever fail. Isn't this test essentially the equivalent of:

Person person = new Person("a", 1)
Person expectedPerson = new Person("a", 1)
assertEquals(person, expectedPerson)

I understand unit testing should test functionality in isolation. Will this test just ensure that mockPersonClient exists at runtime?

Nanor
  • 2,400
  • 6
  • 35
  • 66

2 Answers2

0

We can configure a mock object to always return a hard coded and fake object when calling a method on that mock object.

In this example , the OP configured mockPersonClient.getPerson() return a fake Person.However, he just wonder why the fake person was not returned as configured when he called mockPersonClient.getPerson(). I think the codes example he shown was just for him to demonstrate this question. It does not mean he actually wrote that unit test codes to test some production codes.

Ken Chan
  • 84,777
  • 26
  • 143
  • 172
0

A test like that doesn't have any value.

Here is a person, I am going to ask this call to return person and then I will check I got person when calling that thing. Of course you will get person, you just hard-coded that, so how is it useful?

Unit tests are about functionality, a simple fact which is lost on many. Any code which changes data, which filters something, which changes something in a controlled way, is a good candidate for a unit test.

People use mocks a little bit too much and for most of the time for the wrong thing. Yes, we are advised to code against interfaces, but this doesn't mean you should have a very complex system, where you pass interfaces all over the place and then your test code tries to mimic that.

When you mock too much, it means the test you are writing is tied too much to the code it tests, it knows too much about it. Unit tests should not do that, because every time you change the code in some small way, you then discover that now you have to change the test, because you're no longer using 35 interfaces, now you have 47 to mock in a very specific order. That may not be an issue when you have one test, but imagine what happens when you have 1000 tests ...

If people tried to code in more of a functional way then this would not happen. If you pass data, instead of abstractions, now you don't have to mock anything.

Instead of mocking a call a database, isolate it, take the result and pass that to a method, you've just lost an abstraction and your code does not need to mock anything, you just call the method, pass the data in whatever format you want and see what happens.

If you want to test a real database, then you write an integration test. It's really not that complicated, mocking should not be the first thing you do, do it when it helps and you really must, but most of the time, you really don't and it simplifies things if you don't.

Andrei Dragotoniu
  • 6,155
  • 3
  • 18
  • 32