Java + Powermockito: How to Replace or Mock Thread.sleep method - java

Using PowerMockito, I have been trying to replace or mock the Thread.sleep method.
Wherein, the replacing or mocking method will return and Exception.
I have tried the following examples but no luck:
PowerMockito.replace(PowerMockito.method(Thread.class, "sleep", long.class))
.with((object, method, arguments) -> {
throw new Exception(someRandomExceptionMessage);
});
PowerMockito.when(Thread.class, "sleep", anyLong()).thenThrow(new Exception(someRandomExceptionMessage));
PowerMockito.when(Thread.class, "sleep", 1000L).thenThrow(new Exception("An Exception"));

I guess you have an underTest class calling a function that is using Thread.sleep?
You can rather write your test in this way :
if you have a delay variable that returns the execution duration, you can mock the returned value instead of directly mocking Thread.sleep and then test your exception with #Test(expected = Exception.class) or Exception thrownException = assertThrows() depending on wether you are using JUnit 4 or JUnit 5
if you are using JUnit 5, you can simply use assertTimeout(Duration.ofSeconds(10),() -> { underTest.yourMethodCallingThreadSleep())
if using Mockito, the last version can allows you to mock static methods
Take as a suggestion and a simple way to write your test.

This should work. It is important to note the #PrepareForTest needs to refer the method calling Thread.sleep(), not Thread itself.
class ClassCallingSleep {
public static void methodCallingSleep() throws InterruptedException {
System.out.println("TEST 1");
Thread.sleep(100L);
System.out.println("TEST 2");
}
}
#RunWith(PowerMockRunner.class)
#PrepareForTest({ClassCallingSleep.class})
public class SleepTest {
#Test
public void test() throws Exception {
PowerMockito.mockStatic(Thread.class);
PowerMockito.doThrow(new InterruptedException("HAHA!")).when(Thread.class);
Thread.sleep(Mockito.anyLong());
ClassCallingSleep.methodCallingSleep();
}
}
Output is as follows (that is, TEST 2 above is not reached).
TEST 1
java.lang.InterruptedException: HAHA!

Related

How to test for Exception in #Async method?

How can I assert that a certain exception is thrown inside an #Async method?
Because the following exception is caught by Springs SimpleAsyncUncaughtExceptionHandler.
#Service
public class Service {
#Async
public void run() {
throw new RuntimeException();
}
}
public class Test {
#Test
public void test() {
assertDoesNotThrow(() -> service.run()); //this always passes
}
}
If it is possible for your case, separate testing of asynchronicity and the actual unit of work. E.g. write test that will execute (no 'Async' functionality) Service.run() and assert that no/any/some exceptions are thrown.
In second test (utilizing #Async execution) you could test for the actual unit of work i.e. use your Spring provided bean and test for e.g.:
Awaitility.await().atMost(1000, TimeUnit.MILLISECONDS).untilAsserted(() -> runAnyCodeThatChecksTheResultOfYourServiceRunMethod());
Another method might be to replace the return type of the Service.run() method to java.util.concurrent.Future, Spring will then re-throw the exception. From AsyncExecutionAspectSupport.handleError javadoc:
"If the return type of the method is a {#link Future} object (again, if applicable), the original exception can be propagated by just throwing it at the higher level. However, for all other cases, the exception will not be transmitted back to the client."
import static org.awaitility.Awaitility.await;
Awaitility.await().atMost(5, TimeUnit.SECONDS)
.untilAsserted(() -> assertThrows(RuntimeException.class, () -> service.run()));

How to write junit test for exceptions which are explicitly thrown

I have a method that takes in the String, and check if it contains another string. If it does, then it throws a custom exception.
Class Test{
String s2="test";
public void testex(String s1){
if(s1.contains(s2))
throw new customException();
}
}
I am trying to write a unit test for this:
#Test (expected = customException.class){
when(s1.contains(s2)
.thenThrow(new customException());
}
However, my test is failing with the error as-- java.lang.Exception: Unexpected exception, expected customException but was<org.mockito.exceptions.misusing.MissingMethodInvocationException>
This test doesn't seem to be particularly useful, but I believe your issue is that Mockito's when() expects a method call for a mocked object.
#Test(expcted = CustomException.class)
public void testExMethod() {
#Mock
private Test test;
when(test.testEx()).thenThrow(CustomException.class);
test.testEx("test string");
}
I'm not quite following your example test. It looks like you're mocking your actual class with Mockito rather than writing a junit test. I would write a test like this:
With junit's assertThrows method:
#Test
void stringContainingThrowsError() {
Test myClassThatImTesting = new Test();
assertThrows(CustonException.class, () -> myClassThatImTesting.testex("test"))
}
With a normal assertion:
#Test
void stringContainingThrowsError() {
Test myClassThatImTesting = new Test();
try {
myClassThatImTesting.testex("test");
fail();
} catch (Exception ex) {
assertTrue(ex instanceof CustomException);
}
}

How to assert that void method throws Exception using Mockito and catch-exception?

I'm trying to test this method:
public void deleteCurrentlyLoggedInUser(Principal principal) {
if (findLoggedInUser(principal) == null) {
throw new UserAlreadyDeletedException();
}
userRepository.delete(findLoggedInUser(principal));
}
Here is findLoggedInUser:
User findLoggedInUser(Principal principal) {
return userRepository.findByUsername(principal.getName());
}
And here is my test so far:
#Test
public void shouldThrowExceptionWhenUserNotFound() {
// given
when(sut.findLoggedInUser(principalStub)).thenReturn(null);
// when
sut.deleteCurrentlyLoggedInUser(principalStub);
// then
catchException
verify(userRepositoryMock, never()).delete(any(User.class));
}
So how do I catch exception using catch-exception here? Method that I'm testing returns void and I just can't seem to find a way to assert that exception was found.
EDIT: I know I could use: #Test(expected = UserAlreadyDeletedException.class) but I want to switch my whole project to catch-exception because it's much better and using expected in #Test is not very reasonable.
I've never heard of catch-exception, but it doesn't exactly seem like an up-to-date library: the last update to the main source code (at the time of writing) was on May 3 2015.
If you're using Java 8, and can use JUnit 4.13 or later, you can use assertThrows:
assertThrows(
UserAlreadyDeletedException.class,
() -> sut.deleteCurrentlyLoggedInUser(principalStub));
If you're going to migrate all of your code to something, this seems like a better long-term bet.
It might be that using Rules is something that could work for you?
Rules allow very flexible addition or redefinition of the behavior of each test method in a test class. Testers can reuse or extend one of the provided Rules below, or write their own.
You can read more about this neat feature of junit4 here:
https://github.com/junit-team/junit4/wiki/Rules
Example:
public static class HasExpectedException {
#Rule
public final ExpectedException thrown = ExpectedException.none();
#Test
public void throwsNullPointerException() {
thrown.expect(NullPointerException.class);
throw new NullPointerException();
}
}

Unit testing that log message written when exception caught

Here is the code that I am working with. In this test I want to verify that the log method is being called when an exception is caught.
public class SuperClass(){
public void log()
{
do some logging;
}
}
public class ClassUnderTest extends SuperClass(){
public String methodbeingtested(Object param)
{
try
{
String a = SomeObject.
methodthatthrowsexception(param);//static method, throws JAXB/NPE
}
catch(Exception exp)
{
log("log msg",exp);//inherited method
}
}
}
public class ClassUnderTestTest {
#Test
public testmethodbeingtested(){
ClassUnderTest cut = new ClassUnderTest()
ClassUnderTest cutspy = Mockito.spy(cut);
cutspy.methodbeingtested(param);
Mockito.verify(cutspy).log("log msg", new Exception()); // exp is needed to here.
}
}
After looking at several samples, the above was the closest I could get. This testcase forces an exception. But it fails to verify the log method call as Mockito.verify requires the exact exception (exp) that is caught, which the test case does not have access to.
Is there any other way to test this scenario?
Mockito's verify method can be used with argument matchers. If you want to verify that log was called, with any Exception at all as the second argument, you can just write
verify(cutspy).log(eq("log msg"), any(Exception.class));
I've assumed that you have the right static imports for verify, eq and any.
As an aside, this test does not need PowerMock. Your line PowerMock.expectLastCall().once(); is both redundant and confusing, and should probably be removed, along with the #PrepareForTest annotation.
Instead of spying on ClassUnderTest, you should mock the logging framework, inject it into the class and then verify that the log method gets called. Id' also mock the SomeObject class and have it throw exception.
As an aside, you should really evaluate if you need to verify your log statements. Perhaps you have a valid reason to do so but typically, asserting/verifying to this extent is not required and will only make your tests brittle.

Easymock - nested void method testing (spying)

How to spy parameter 'param' in nested method during getData() mock testing ?
Is it possible with Easymock 3 ?
Source code
public class ServiceLogic {
public void getData(){
// some business logic
serviceDAO.executeStatement(param);
}
}
Easymock test :
ServiceLogic _serviceLogicMock = EasyMock.createNiceMock(ServiceLogic.class);
ServiceDAO _serviceDAOMock = EasyMock.createNiceMock(ServiceDAO .class);
_serviceLogicMock.setServiceDAO(_serviceDAOMock);
//some other method calls -> .execute(...).andReturn(...);
EasyMock.replay(_serviceLogicMock);
//run
_serviceLogicMock.getData();
How to check with EasyMock whether executeStatement() method is called with correct parameter ?!
Your test does seem wrong:
Your unit test is about testing ServiceLogic why do you mock it then ?
Also you don't have any expectations on any interaction with your ServiceDAO mock.
As the question is tagged Mockito, I propose the following solution (minus the imports) that you can adapt to your code :
#RunWith(MockitoJUnitRunner.class)
public class ServiceLogicTest {
#Mock ServiceDAO serviceDAO;
#InjectMocks ServiceLogic serviceLogic;
#Test
public void ensure_executeStatement_is_called_with_right_param() throws Exception {
// given
String input = "Some input";
// when
serviceLogic.getDataFrom(input);
// then
verify(serviceDAO).executeStatement("expected param");
}
}
When writing tests, I like to use the BDD (Behavior Driven Development) style to guide me to what I want to test. I encourage you to practice it, you can have look at the wiki page.
So for your question, you should take a look at the verify line, it put the mock in a verification mode, so can actually verify that the method executeStatement is actually called with the argument value "expected param".
If you have more complex parameters, you can use some matchers using the Hamcrest library:
verify(serviceDAO).executeStatement(argThat(hasProperty("propertyName")));
Or you can use a Mockito's ArgumentCaptor in combination with the FEST-Assert library (usually my preferred approach):
ArgumentCaptor<ComplexArgument> argCaptor = ArgumentCaptor.forClass(ComplexArgument.class);
verify(serviceDAO).executeStatement(argCaptor.capture());
assertThat(argCaptor.getValue()).isNotNull().satisfies(myComplexArgumentCondition());
The main idea is to have understandable code, in production code and in test code.
For further reading have a look at the Mockito Javadoc.
Like #Brice, I prefer Mockito to EasyMock, but here's the EasyMock version that is closer to your original example since your example was EasyMock.
public class ServiceLogicTest {
#Test
public void ensure_executeStatement_is_called_with_right_param() throws Exception {
ServiceLogic _serviceLogicUT = new ServiceLogic();
ServiceDAO _serviceDAOMock = EasyMock.createNiceMock(ServiceDAO .class);
_serviceLogicUT.setServiceDAO(_serviceDAOMock);
String input = "Some input";
//some other method calls -> .execute(...).andReturn(...);
_serviceDaoMock.executeStatement("expected para"); // assuming a void method
EasyMock.replay(_serviceDaoMock);
// run
_serviceLogicUT.getDataFrom(input);
// verifies that the expected calls were made
EasyMock.verify(_serviceDaoMock);
}
}
EasyMock also has argument capture functionality. That would look like this:
public class ServiceLogicTest {
#Test
public void ensure_executeStatement_is_called_with_right_param() throws Exception {
ServiceLogic _serviceLogicUT = new ServiceLogic();
ServiceDAO _serviceDAOMock = EasyMock.createNiceMock(ServiceDAO .class);
_serviceLogicUT.setServiceDAO(_serviceDAOMock);
String input = "Some input";
//some other method calls -> .execute(...).andReturn(...);
Capture<ComplexParam> capturedParam = new Capture<ComplexParam>();
_serviceDaoMock.executeStatement(EasyMock.capture(capturedParam)); // assuming a void method
EasyMock.replay(_serviceDaoMock);
// run
_serviceLogicUT.getDataFrom(input);
ComplexParam actualParam = capturedParam.getValue();
// make various assertions on actual param
}
}
I think you can see from the two examples why many people prefer Mockito, but if there's some reason you prefer or are mandated to use EasyMock, you can do just about anything you can do with Mockito, just with more lines of code.
This should be possible with jmockit, unless you DAO has final methods. However, this is better and easier done with jMockit:
#Test
public void testMethod(#Mocked final ServiceDAO serviceDAO) {
new Expectations() {{
serviceDAO.executeStatement(expectedOParams);returns(expectedReturnValue)
}};
(new ServiceLogic(serviceDAO)).getData();
}
That's almost complete test save assertions. And it works with final, static, abstract and whatever methods.

Categories

Resources