Mock an Eureka Feign Client for Unittesting

后端 未结 3 1444
南笙
南笙 2020-12-16 00:41

i am using spring cloud\'s eureka and feign to communicate between some services (lets say A and B). Now id like to unittest my service layer of a single service (A). The pr

相关标签:
3条回答
  • 2020-12-16 00:44

    Mocking a feign client is really useful in microservice component tests. You want to test one microservice without having to start all the other microservices.

    If you're using Spring (and it looks like you are), the @MockBean annotation together with a bit of Mockito code will do the job.

    @RunWith(SpringRunner.class)
    @SpringBootTest(webEnvironment = 
    SpringBootTest.WebEnvironment.DEFINED_PORT)
    public class TestYourComponent {
        @Configuration
        @Import({YourConfiguration.class})
        public static class TestConfiguration {
        }
    
        @MockBean
        private UserClient userClient;
    
        @Test
        public void someTest()
        {
            //...
            mockSomeBehavior();
            //...
        }
    
        private void mockSomeBehavior() {
            Mockito.doReturn(someKindOfUser).when(userClient).getUser();
        }
    }
    
    0 讨论(0)
  • 2020-12-16 00:44

    If you need to use a mock you can use Wiremock to stub the response for a given request - http://wiremock.org/stubbing.html. That way you will do integration tests with real HTTP requests sent. For unit testing the answer from @Markon is very good.

    0 讨论(0)
  • 2020-12-16 00:54

    The question is ... do you even need to mock? I often see that people mention "mock" as the first solution to anything that "should not be part of the unit test". Mocking is a technique, not the solution to everything. (see here).

    If you are still at the early stages of your code, just refactor and use something else instead of depending on the concrete instance of the Feign Client. You might use an interface, an abstract class, a trait or whatever you want. Don't depend on the object itself, otherwise you have to "mock it".

    public interface IWebClient {
      public String get(...);
      public String post(...);
    } 
    

    To the question: but I will have other code that will do exactly the same (except that it will be on the concrete instance of Feign), what do I do then? Well, you can write a functional test and call an instance of a web server that you can setup locally - or use Wiremock, as mentioned by Marcin Grzejszczak in one of the answers.

    public class FeignClientWrapper implements IWebClient {
      private feign = something
    
      public String get() {
        feign.get( ... ) 
      }
    
      public String post() {
        feign.post( ... ) 
      }
    } 
    

    Unit tests are used to test algorithms, if/else, loops: how units work. Don't write code to make mocks fit - it must be the other way around: your code should have less dependencies, and you should mock only when you need to verify the behavior (otherwise you can use a stub or a fake object): do you need to verify the behavior? Do you need to test that a particular method gets called in your code? Or that a particular method gets called with X, Y, and Z for 3 times in a row? Well, then yes, mocking is ok.

    Otherwise, use a fake object: what you want is to test just the call/response and maybe the status code. All you probably want is to test how your code reacts to different outputs (e.g., the field "error" is present or not in a JSON response), different status codes (assuming that the Client documentation is right: 200 OK when GET, 201 when POST, etc).

    0 讨论(0)
提交回复
热议问题