问题
I am testing a method which is protected
. In my test case I've used Reflection
to access the method but I am not exactly sure whether I am doing it in a right way.
Method to be tested:
protected void checkORCondition( Map<String, Message> messagesMap ) throws EISClientException
{
Message message = containsAMessageCode(getMessageCodes(), messagesMap);
if(message!=null)
{
throw new EISClientException("One of the specified message code matched returned errors." +
message.getMessageCode() + ": " + message.getMessageType() + ": " + message.getMessageText());
}
}
JUnit test case:
@Test
public void testcheckORCondition() throws Exception {
Class clazz = MessageToExceptionPostProcessFilter.class;
Object object = clazz.newInstance();
Method method = clazz.getDeclaredMethod("checkORCondition", new Class[]{Map.class});
method.setAccessible(true);
String string = new String();
string = "testing";
Message message = new Message();
message.setMessageCode("200");
Map<String, Message> map = new HashMap<String, Message>();
map.put(string, message);
assertEquals("testing", string);
assertEquals("200", message.getMessageCode());
}
My JUnit passes but not sure if it going inside the method.
回答1:
Best way is to put the protected methods under same package name under test. This will ensure that they are accessible. Check junit FAQ page http://junit.org/faq.html#organize_1
回答2:
Using reflection to access protected methods from a unit test seems heavy handed. There are several easier ways to do this.
The easiest way would be to make sure your tests are in the same package hierarchy as the class you are testing. If that's not possible then you can subclass the original class and create a public accessor that calls the protected method.
If it's a one-off case then it could even be as simple as making an anonymous class.
Class you want to test:
public class MessageToExceptionPostProcessFilter {
protected void checkOrCondition(Map<String, Message> messagesMap) throws EISClientException {
// Logic you want to test
}
}
And your test class:
public class MessageToExceptionPostProcessFilterTest {
@Test
public void testCheckOrCondition() throws Exception {
String string = "testing";
Message message = new Message();
message.setMessageCode("200");
Map<String, Message> map = new HashMap<>();
map.put(string, message);
MessageToExceptionPostProcessFilter filter = new MessageToExceptionPostProcessFilter() {
public MessageToExceptionPostProcessFilter callProtectedMethod(Map<String, Message> messagesMap) throws EISClientException {
checkOrCondition(messagesMap);
return this;
}
}.callProtectedMethod(map);
// Assert stuff
}
}
回答3:
It doesn't go inside the method as you don't call it. Use invoke
to call it:
method.invoke(this_parameter, new Object[]{ map });
Other than that, there is no good solution. One recommendation is to put the test into the same package and make it package visible, but there are lot of cons as the method will not be visible by inherited classes.
I believe the way you chose is good one.
回答4:
Use a mocking library to create a subclass as part of your test.
来源:https://stackoverflow.com/questions/35186648/testing-protected-method-with-junit