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.

Mick F
  • 7,312
  • 6
  • 51
  • 98
  • 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. – Jim Garrison Aug 21 '13 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 Aug 22 '13 at 14:55

2 Answers2

2

I think the workaround is to escape the characters like

String password = ":&=/?\u00e9$\u00a3";
  • thanks, your solution was interesting but i had a preference with the one i've used for readability of the test. – Mick F Aug 22 '13 at 15:14
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.

Community
  • 1
  • 1
artbristol
  • 32,010
  • 5
  • 70
  • 103
  • 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 Aug 22 '13 at 15:09