Today I pushed up a new release of Watson Workspace Java SDK to OpenNTF. This includes all mutation GraphQL queries, namely:
As ever, the documentation has been updated and full Javadoc comments added. As before, the documentation includes examples.
This has been a big learning curve, building up my skills more on unit testing. The challenge has been that all of these mutations can only be run under a user’s authority. They fail if run just authenticated as an application. But there is no endpoint to programmatically authenticate and permit authorisation as a user. That requires a browser login which returns a code for the relevant user, scope and redirectUrl. The code is then what’s passed – with the application key and secret – to the user authorization.
My first attempt was to use the technique of simulating OAuth2 login using Hoverfly and WebDriver. This should allow creating a FirefoxDriver to simulate Selenium tests to programmatically run through the various web pages for authentication. However, I couldn’t get it to work.
Part of this seemed to be because I wanted to parameterise the tests, passing things like my username and password from the Run Configuration in Eclipse rather than hard-coding them in the script, which is obviously not good. I came to realise that the way that’s done in Watson Work Services Java SDK is to use TestNg. With TestNg tests are run during a Maven build. This, as I came to appreciate, is very different to JUnit, which allows tests to be run standalone.
But there are other differences between TestNg and JUnit, more critical ones. After various searching, I became aware that JUnit has @BeforeClass and @AfterClass annotations, which the FirefoxDriver uses to set up and tear down various things. This is why the blog post and Hoverfly Java library is using JUnit and why I was getting errors relating to com.sun.jersey.spi. So I decided to commit to using JUnit. With JUnit, it is possible to pick up variables from Eclipse using
System.getenv(), but those variables don’t get picked up by a Maven build. So the JUnit tests can only be run manually and will fail during a build unless disabled. Even then I still couldn’t get it to work.
I was able create JUnit tests manually by getting the user’s token code via a browser and in my unit test authenticating as a user with the token code and same redirect URL. However, the code can only be used once, so I needed to get a new code each time. This made it rather problematic for integrating with run configurations.
My final fallback, thanks to suggestions from the community, was to avoid end-to-end tests and instead test the JSON generated for a query against JSON copied from the Watson Work Services GraphQL IDE (I’ve been doing that for a while). But then to create a mock endpoint into which I could post the JSON response from the GraphQL IDE and allow my API code to parse.
This is guaraneteed to work regardless of whether I’m connected to the internet and regardless of whether the service is available or not. I appreciate the benefit of that. But for two reasons, that’s not important to me. Firstly, I’m unlikely to rely on a full Maven build when not connected to the internet. Secondly, if Watson Work Services (or any cloud API frankly) is not available when I am connected to the internet and critically need it, that’s makes a good reason in my mind for not using the service.
The downside of using the mock endpoints is I’m only ever testing that I haven’t broken my code, because I’m testing JSON I’ve generated at some point in the past against the API I’ve coded. I will not know if something has been changed at the other end that breaks my code. And if I am notified of a breaking change, the only way I can test is to fall back on a test where I manually retrieve a code via a browser and use that in a one-time attempt.