Javalin: Proper testing pipeline

Created on 27 Sep 2018  路  5Comments  路  Source: tipsy/javalin

Hello,

I'm in the process of evaluating Javalin in Java to replace a Spring service that is in the making.
So far I'm excited about the simplicity but power and control it has.

I am wondering on how to properly unit test the controllers. In Spring, there is the possibility to "mockMvc".

In Javalin, I am testing the controllers' handle(ctx).
Unfortunately, this does not work very well, because some classes are not mockable, e.g. the result from ctx.validatedBodyAsClass(...).

Alternatively, I could also mock HttpServletRequest with mockito. But this would result in mocking-hell, because I would have to mock every sub-object, like the writers, etc...

Or create a complete HttpServletRequest-implementation for testing.

How are you unit-testing your controllers? Do you have guidelines and examples in Java?

Thanks!

QUESTION

Most helpful comment

If you can write your tests in Kotlin that would be a great solution. I don't remember if I added any mock tests to the repo. I should probably write a tutorial.

All 5 comments

Hi @JosefEvAlloc, mocking was discussed in https://github.com/tipsy/javalin/issues/335. The conclusion was:

  • If you're using Java, mock HttpServletRequest and HttpServletResponse, then pass them to ContextUtil.init(). The init function is overloaded to take all the dependencies of Context:
Context ctx = ContextUtil.init(req, res);
Context ctx = ContextUtil.init(req, res, "/:param");
Context ctx = ContextUtil.init(req, res, matchedPath, pathParams);
Context ctx = ContextUtil.init(req, res, matchedPath, pathParams, splats);
Context ctx = ContextUtil.init(req, res, matchedPath, pathParams, splats, handlerType);

As Javalin is growing in popularity I see more and more Java developers wishing for better mocking support. I mostly write Kotlin, where mocking is relatively painless (You can mock Context and it's methods without having to mock any underlying objects).

If you're interested in providing better mocking support for Java I'd be happy to assist you with code-reviews and discussion. I want to avoid structuring the codebase around mockito's requirements (like creating interfaces that are implemented once), but other than that I'm very open to suggestions.

Hi @tipsy,

thanks for the fast reply!
I have read the conversation and seen the ContextUtil.init functions and used them, they are useful to a certain degree.

It is totally understandable that this framework shouldn't be centered around mockito or that it should be taylored just for one testing framework.

I am not familar with Kotlin, so I can't compare how much easier it is to test there.

From the Java perspective:

Given these mocks

  req = Mockito.mock(HttpServletRequest.class);
  res = Mockito.mock(HttpServletResponse.class);
  Context ctx = ContextUtil.init(req, res, "/:param");

And this code in the handler: Someclass request = ctx.validatedBodyAsClass(Someclass.class).getOrThrow()

Makes the handler only testable with a lot of effort, by either

  • implementing a whole HttpServletRequest class with all features, or
  • reading deep into the Javalin code and try to mock the the HttpServletRequest sub-objects utilized by the ctx functions

I will search for a solution that doesn't consume too much time. Might be it is an option to switch the testing to Kotlin?

If you can write your tests in Kotlin that would be a great solution. I don't remember if I added any mock tests to the repo. I should probably write a tutorial.

Just wanted to share my thoughts on this, from a Java-dev perspective. Please note, that this is just my relatively unfiltered opinion and I don't expect anybody to agree on this.

It seems the easiest way to get mocks/unit tests working, is to enable mocking of finals in mockito as described here: https://github.com/tipsy/javalin/issues/335#issuecomment-415845558.
This enables short, precise mocks for unit tests with very few lines of code, but needs nested mocks.

I'm not a fan of mocking finals and nested mocks. If I had such such requirements to test my code, I would see it as a code smell and refactor it until it is easily mockable. Doing it the Java way, with - yes - interfaces. The code is then not taylored towards a testing framework, but when it is easily mockable, it is testable with a lot of various frameworks and doesn't need "specific framework X" for testing.

Also, learning Kotlin (gave it a thought) is not an option. I picked Javalin for Java, its simplicity and its straightforward functionality (away from Spring, for example). Having to learn Kotlin, just to be able to test the code is the wrong direction and would take a lot of the traction away.

I see, that you @tipsy are open for Java testing support. I am very thankful for this wonderful, uncomplicated framework and the way you handle things around here. It seems that easy testing with Java will be available someday :-)

Does the context object need all the functions? Couldn't some functions be part of a sub-object? From an OO standpoint, it seems that the context object is doing too much at once.

Does the context object need all the functions?

IMO, yes. You could argue that a lot functions could be moved into Request and Response classes on the Context, but that would instantly add a lot of noise to controllers (ex: calling ctx.request().pathParams(":user-id")). You could also make an interface which takes a Context, a Request, and a Response, but that would similarly create a lot of noisy method signatures and lambdas.

I went through the different alternatives when designing the API, and this was found to be the best solution.

I'm worried that by introducing single implementation interfaces, the code will be harder to read and understand for new users and new contributors (this also worries me about nesting functionality into different objects on the Context).

Was this page helpful?
0 / 5 - 0 ratings

Related issues

maxemann96 picture maxemann96  路  5Comments

mikexliu picture mikexliu  路  3Comments

mkpaz picture mkpaz  路  4Comments

valtterip picture valtterip  路  5Comments

jonerer picture jonerer  路  4Comments