user1615376
user1615376

Reputation: 81

Using MockBean in Micronaut with lambda runtime for Lambda Application

I have a simple Micronaut Lambda Application and am having difficulty in successfully getting Mocks injected in to my unit tests.

build.gradle

micronaut {
    runtime("lambda")
    testRuntime("junit5")
    ...
}

With the following basic Controller

@Controller
public class MyController{

  Service service;

  @Inject
  public Controller controller(Service service){
    this.service = service;
  }
 
  @Post("/test")
  public void someEndpoint(){
    service.doSomething();
  }
}

And the following test class:

@MicronautLambdaTest
public class MyControllerTest{

  @Inject
  Service service;

  @Inject
  @Client("/")
  RxHttpClient rxHttpClient;
  
  @MockBean(Service.class)
  Service service() {       
    return mock(Service.class);
  }

  @Test
  void should_do_something_when_something(){
    rxHttpClient.toBlocking().exchange(HttpRequest.POST("/test",""));
    verify(service, times(1)).doSomething();
  }
}

The test above will fail as the mock is never interacted with.

When debugging I can see that the Service is mocked in the test class itself, but in the MyController class there is an actual object being used.

I notice that when I am not using runtime("lambda") (e.g. runtime("netty")) this works as expected, so I think this is something to do with the Lambda runtime, and am hoping someone may be able to point me in the right direction here.

Upvotes: 1

Views: 1011

Answers (1)

berty
berty

Reputation: 170

When using runtime("lambda"), you need to start the test using your handler class and remove the @MicronautTest.

MicronautLambdaHandler handler = new MicronautLambdaHandler();

This will start the application context.

You can also pass arguments using ApplicationContext.builder()

ApplicationContextBuilder config = ApplicationContext.builder()
                .environments("test");
MicronautLambdaHandler handler = new MicronautLambdaHandler(config);

Running the test with @MicronautTest and runtime("lambda") runs two set of environment separately that's why I removed the @MicronautTest.

If you still want to mock classes. You can create a mock class and annotate it with @Replaces(ClassToMock.class) and @Requires. For me it's @Requires(env = Environment.TEST).

For classes that is not an implementation of an interface, you need to extend the class you want to mock (I'm using v2.5.6).


@Replaces(ClassToMock.class)
@Requires(env = Environment.TEST)
@Singleton
public class MockClass extends ClassToMock {

   @Override
   public void someMethod() {}
}

For classes that implements an interface, you can simply create another implementation and annotate it likewise.

Upvotes: 3

Related Questions