Injecting messages for validation testing
Hopefully there's a quick and easy answer for this one.
I'm starting unit testing on my project. The class in question is essentially a form with some fields and the following validate method:
Code:
public boolean validate(MessageContext context)
Inside the message, I'm using MessageBuilders to construct the message, using a code to generate the message text referencing the resource bundle for the flow.
For the purposes of testing, I'm setting various properties of the form, then calling validate() passing in a DefaultMessageContext. However, not surprisingly, the codes I'm passing to my MessageBuilder aren't being evaluated since it isn't referencing my properties file.
I can't seem to figure out where to configure this so my properties file gets read so my messages resolve correctly. Can someone point me in the right direction?
As a side question, I'm looking for a way to universally get at my resources. During development, I typically run my test classes directly. But our test classes are also a part of our ant build process. The working directories when executing each are different, so I can't be sure of where I am in the directory structure so it's difficult to figure out how to get to the web/WEB-INF/flows/... etc. This seems like a common problem, so I'm hoping there's a common solution to this one as well.
Write Your Own MessageSource
So originally we used a StaticMessageSource approach where we created a message source with all the appropriate codes and then tested against it. That became a pain to maintain and so I took an alternate approach:
Write your own testMessageSource. Mine looks like this:
Code:
public class TestMessageSource extends AbstractMessageSource {
/**
* Resolve code returns a message with the code and ignores Locale
* @param code
* @param locale
* @return
*/
protected MessageFormat resolveCode(String code, Locale locale) {
return createMessageFormat(code, locale);
}
}
If you use this as your message source, it will always insert a message with the code itself as teh message. So you can do things like:
Code:
public void testPhaseIsBlank() throws Exception {
TestMessageSource source = new TestMessageSource();
DefaultMessageContext ctx = new DefaultMessageContext(source);
EditForm epf = new EditForm();
epf.setPhase(null);
epf.validateSave(ctx);
assertMessageExists("editForm.noPhase", ctx);
}
public static void assertMessageExists(String msg, MessageContext msgs) {
for (Message message : msgs.getAllMessages()) {
if (message.getText().contains(msg)) {
return;
}
}
Assert.fail("msg '" + msg + "' not found in msgs: " + msgs);
}
Obviously, this doesn't test that your messages resource contains the right codes but that's a much more complicated issue (because some messagebuilders might specify default messages, etc.). We actually solve that by code analysis (ie, look for all messagebuilders, find all message codes, make sure they are in the resource file) rather than testing.
Hope this helps!