0

I have an encoding based unit test in my project. The test passes in Eclipse but fails with Maven.

All my files are UTF-8 encoded and I added the 2 following lines in my pom.xml but the test keeps failing:

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>

Here is the interesting part of the test. Credentials is a simple bean storing the password as a String with getter/setter (no other code there).

AuthentificationHelper helper = new AuthentificationHelper();
// ...
String password = ":&=/?é$£";
String base64Hash = Base64.encodeString(login + ":" + password);
final String authHeader = "Basic " + base64Hash;
// ...
Credentials credentials = helper.credentialsWithBasicAuthentication(request);
assertEquals(password, credentials.getPassword());

The credentialsWithBasicAuthentication does the reverse operation of what's being done here:

StringTokenizer st = new StringTokenizer(authHeader);
//...
String credentials = new String(Base64.decodeBase64(hashedCredentials), "UTF-8");
int p = credentials.indexOf(":");
//...
String password = credentials.substring(p + 1).trim();
return new Credentials(login, password);

Here is Maven's output:

Failed tests: 
   testCredentialsWithBasicAuthentication: expected:<:&=/?[?$?]> but was:<:&=/?[?$?]>

(not sure if this is relevent but my log4j appender is also configured to output data in UTF-8)

Any idea what's wrong? (the surprising part being that the console output is not displayed properly either)

SOLUTION (embarassing)

The Base64 class I was using was not the one provided by Apache Commons but a random one.

Replacing:

import random.bla.bla.Base64;
// ...
String base64Hash = Base64.encodeString(login + ":" + password);

by

import org.apache.commons.codec.binary.Base64;
// ...
String base64Hash = Base64.encodeBase64String(new String(login + ":" + password).getBytes("UTF-8"));

solved the problem.

Cough, cough, tumbleweed.

2
  • There's a lot of missing info here. What is credentials.getPassword()? How is the data traveling from the first block of code to the test? How is the expected value declared and encoded? This is unanswerable without a lot more detail. Commented Aug 21, 2013 at 18:19
  • @Jim Garrison, updated the question a bit but the hidden code doesn't do anything smart about encoding. The relevant bits are here.
    – Mick F
    Commented Aug 22, 2013 at 14:55

2 Answers 2

2

Base64.encodeString(login + ":" + password) is implicitly using a character encoding (the platform default, which could conceivably be different between Maven and Eclipse), because it has to convert the string to a byte array before it can hash it. You should specify it explicitly - presumably ISO-8859-1, see this question What encoding should I use for HTTP Basic Authentication?.

It's also possible that Eclipse has a different idea of the source file's encoding than Maven (you can check by right clicking the file and doing Properties). Usually m2e sorts that out for you.

An aside - why are you writing code to deal with HTTP authentication? You should use a library.

1
  • As a matter of fact, your answer (and Jim Garrison's comment) helped me realized the Base64 class i was using wasn't Apache's one but one some random class provided by another library my project depends on. I've updated the question with the solution.
    – Mick F
    Commented Aug 22, 2013 at 15:09
2

I think the workaround is to escape the characters like

String password = ":&=/?\u00e9$\u00a3";
1
  • thanks, your solution was interesting but i had a preference with the one i've used for readability of the test.
    – Mick F
    Commented Aug 22, 2013 at 15:14

Not the answer you're looking for? Browse other questions tagged or ask your own question.