el n00b
el n00b

Reputation: 1863

Strategy for Spring, Feign and TestNG

I currently have a project using TestNG to execute tests against my Spring project. Within my project I have a set of Feign interfaces that handle external calls on my Eureka configuration. I am having difficulty understanding how to mock/intercept these calls on a test-by-test basis during execution.

Here is an example of one of my Feign interfaces:

@FeignClient ("http://my-service")
public interface MyServiceFeign {

    @RequestMapping (value = "/endpoint/{key}", method = RequestMethod.GET)
    SomePojo getByKey(@PathVariable ("key") String key);
}

I have a service that relies on the client:

@Service
public class MyService {

    @Autowired
    private MyServiceFeign theFeign;

    public SomePojo doStuff() {
      return theFeign.getByKey("SomeKey");
    }
}

My tests are launched simply via:

@SpringBootTest (
    classes = Service.class,
    webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT
)
@TestExecutionListeners (
    inheritListeners = false,
    listeners = {
        DependencyInjectionTestExecutionListener.class,
        TransactionalTestExecutionListener.class
    }
)
@DirtiesContext
@ContextConfiguration (initializers = CustomYamlLoader.class)
@ActiveProfiles ("test")
publi class MyModuleTest extends AbstractTestNGSpringContextTests {
    // ....
}

What I want to do in my test is execute something like this:

@Test
public void doSomeTest() {
   SomePojo fakeReturn = new SomePojo();
   fakeReturn.setSomeStuff("some stuff");

   /*
     !!! do something with the injected feign for this test !!!
     setupFeignReturn(feignIntercept, fakeReturn);
   */

   SomePojo somePojo = injectedService.doStuff();
   Assert.assertNotNull(somePojo, "How did I get NULL in a fake test?");
}

So, here's my dilemma: I am missing a key understanding to be able to do this, I think. That or I am completely missing the concept of how this should be handled. I don't think that using a fallback implementation makes sense here, but I could be wrong.

Help!

Upvotes: 3

Views: 671

Answers (1)

David Steiman
David Steiman

Reputation: 3145

as far as I understand you are dealing with feign clients (and possibly ones with security on top, like basic auth or OAuth2), and want to do tests. But actually, the attend is not to test MyServiceFeign is working, but MyService is working properly, given the feign client retrieves a valid result.

For this purpose, you do not actually inject your feign client, you mock it.

In short, this can be achieved by two steps: using @MockBean instead of @Autowired and describe your clients behavior before you use it.

@RunWith(SpringRunner.class)
@SpringBootTest(classes = YourApp.class)
public class MyServiceUnitTest {

    @MockBean
    private MyServiceFeign myFeignClient;

    @Autowiered
    private MyService myService;

    @Test
    public void testSync() {
        given(myFeignClient.getByKey("SomeKey")).willReturn(
            new SomePojo("SomeKey")
        );
        assertEquals("SomeKey", myService.doStuff().getKey());
    }
}

as already said, Mockito is used by spring for this way of testing components. I describe a more advanced setup with oauth2 intercepting and two ways of testing oauth2 intercepted feign clients.

Upvotes: 1

Related Questions