Reputation: 22923
I have a test where I have written most the unit tests I need, but there is one I want to test the first bits of the logic. I don't care what happens in the rest of the method as long as the method has been called, but since the SUT fails with an NPE due to lack of further mocking, the test fails before I get to my assertion.
Is there a clean way of asserting a method was called and ignore all exceptions happening after that? Perhaps some kind of blocking behavior on hitting the method and aborting/passing the test after that?
I was thinking I could write when(mock.methodIAmInterestedIn(any)).thenThrow(new RuntimeException("verified!"))
and then simply assert that I get the right exception (it will be wrapped inside another, though). This would probably work, but it is a bit unclean: obscuring what I really want to test.
@Test
public void should_load_using_filename_in_config() {
loader = new OrgUnitLoader(config, dbSupport.mockServices);
config = mock(TestConfiguration.class);
/* further mocking of the config needed if I am not to get an NPE */
when(dao.orgUnitsAreLoaded()).thenReturn(false);
// call the actual method
loader.loadOrgUnits();
verify(config, times(1)).getString(ORG_UNIT_DATA_FILE);
}
Could a CountdownLatch
be used, for instance?
Upvotes: 1
Views: 144
Reputation: 5173
Since you know that your test loader/configuration is incomplete, you are expecting the method to fail at some point. Consider it in your test:
@Test
public void should_load_using_filename_in_config() {
loader = new OrgUnitLoader(config, dbSupport.mockServices);
config = mock(TestConfiguration.class);
/* further mocking of the config needed if I am not to get an NPE */
when(dao.orgUnitsAreLoaded()).thenReturn(false);
try {
// call the actual method
loader.loadOrgUnits();
Assert.fail("Should fail as config is incomplete.");
} catch (NullPointerException e) {
verify(config, times(1)).getString(ORG_UNIT_DATA_FILE);
}
}
EDIT (following comments)
Catching only the expected NPE excludes other exceptions. Should a NPE be thrown before dao.orgUnitsAreLoaded()
is called verify(...)
will fail. You'll notice it.
Maybe this isn't very sophisticated but it is very simple and easy (KISS) to understand - even later by other.
@see Junit assert something after awaiting and handling an exception
Upvotes: 0
Reputation: 15622
I want to test the first bits of the logic. I don't care what happens in the rest of the method
This looks like your code under test fails the Single Responsibility Pattern.
You might concider to extract the independent parts of that method to separate methods or even better to Objects of their own. In result your current method would become a composed method using some dependencies with very small logic that would be easy to test.
there are two obvious downsides:
- I would then need to open up the SUT, making lots of internal methods that naturally should be private, into ones with package access to be able to test them. – oligofren
The point is that there is an obvoius need to verify the dispatch behavior independendly from the actual business logic stuffed into the current method. This tells me that this dispatch behavior is a responsibility of its own that sould be separated from the rest or the method.
To me it looks that all the other logic belongs to other classes, not only separate methods in the same class.
This is a consequence from the Same level of abstraction principle that we should apply to classes as well as to methods. This new classes indeed would provide at least package private
access to their interface.
- I would be very tightly bound to the internals of the SUT, but I guess I am already doing that ... – oligofren
This "tightly binding" might only exist in your head knowing the actual implementation. The fact that you have a need to split up the code for testing shows that the code is less tighly bounded as you think.
I guess there is a certain bit of pragmatism involved in all unit testing decisions (test-only code, opening up, ...). – oligofren
There is a quite simple rule about unittesting that avoids all that "pragmatical decisions" stuff:
UnitTest do not test code, UnitTest verify public observable behavior where public means: return values and communication with dependencies.
There is not room for "pragmatical decisions". The only decision is: what is the expected behavior of the CUT?
Upvotes: 2
Reputation: 82
Why you don't use CompletableFuture
, you can create an instance of this class with a no-arg constructor to represent some future result, hand it out to the consumers and complete it at some time in the future using the complete method. The consumers may use the get method to block the current thread until this result will be provided.
Upvotes: 0