I am trying to test async method with timeout.
When I am calling the method directly the method run asynchronically and throw TimeoutException as expected. But when I stub the method, the method run synchronically and TimeoutException is not thrown. What am i doing wrong?
Class A()
{
#Async
public Future<Integer> asyncMethod(){
Thread.sleep(5000);
return new AsyncResult<>(1);
}
}
Class B()
{
A a;
#Autowired
B(A a)
{
this.a=a;
}
public void syncMethod()
{
Future<Integer> futureResult = a.asyncMehod();
// 2sec < 5sec, expect to throw TimeoutException
futureCount.get(2, TimeUnit.SECONDS);
}
}
Class TestBMockBean()
{
#MockBean
A a;
B b;
#BeforeAll
public void init()}{
this.b = new B(a);
}
// This test failed
#Test
void syncMethod() {
when(a.asyncMethod()).thenAnswer((Answer<AsyncResult<Integer>>) invocation -> {
Thread.sleep(5000);
return new AsyncResult<>(0);
});
}
assertThrows(TimeoutException.class,()-> b.syncMethod());
}
}
Class TestBAutowired()
{
#Autowired
B b:
// This test pass
#Test //success
void syncMethod_autowired() {
assertThrows(TimeoutException.class,()-> b.syncMethod());
}
}
Related
What is the general approach in unit tests for methods that involve a sleep() call?
Lets say I have the class:
class Foo {
public bool someMethodWithSleep() {
bool failed = false;
for (int i = 0 : 5) {
failed = trySomething(); // mocked to return false
if (failed) {
TimeUnit.SECONDS.sleep(5);
} else { return true; }
}
return false;
}
}
In test cases for failures that call this function (directly or nested), I dont want it to sleep for 25+ seconds and slowing every test file that calls it. What's the best approach to skip the sleep calls in unit tests?
Replace it with a dependency.
class Foo {
private final Sleeper sleeper;
public Foo(final Sleeper sleeper) {
this.sleeper = sleeper;
}
public Foo() {
this(SecondsSleeper.INSTANCE);
}
public bool someMethodWithSleep() {
bool failed = false;
for (int i = 0 : 5) {
failed = trySomething(); // mocked to return false
if (failed) {
sleeper.sleep(5);
} else { return true; }
}
return false;
}
}
interface Sleeper {
void sleep(int duration);
}
enum SecondsSleeper implements Sleeper {
INSTANCE;
void sleep(final int seconds) {
TimeUnit.SECONDS.sleep(seconds);
}
}
enum TestSleeper implements Sleeper {
INSTANCE;
void sleepSeconds(final int duration) {
// do nothing
}
}
Then in your real application, create Foo as new Foo() and in your test as new Foo(TestSleeper.INSTANCE)
I'm trying to mock Class D constructor. yet, the mocked objects invokes the real function instead of just returning the value.
Read from bottom.
Main
public abstract class F
{
int hi()
{
throw new Exception("I always throw Exception. So don't execute me");
return 1;
}
}
public abstract class E extends F
{
int hi()
{
return super.hi();
}
}
public class D extends E
{
}
public class C
{
D d_object;
C()
{
d_object = new new D(); // will be mocked_d!
}
int hi()
{
d_object.hi();
}
}
public class B
{
void fun()
{
C object = new C();
int value = object.hi();
}`
}
Test
#RunWith(PowerMockRunner.class)
#PowerMockRunnerDelegate(SpringJunit4ClassRunner.class)
#PrepareForTest({C.class,D.class})
public class Test_B
{
#Autowired
A o_A;
#Test
public void test_method()
{
D mocked_D = mock(D.class);
PowerMockito.whenNew(D.class).withNoArguments().then(new Answer()
{
#Override
public Object answer(InvocationOnMock invocation) throws Throwable
{
return mocked_D;
}
});
PowerMockito.doReturn(2).when(mocked_d).hi();
Assert.assertEquals(2,o_A.fun()) // throws Exception. since method inside class F gets executed.
}
}
hi() method inside class F always gets invoked, hence it throws execution. I don't want to invoke that function. am I doing anything wrong?
When using #PrepareForTest I always use PowerMockito.mockStatic method inside tests.
I create simple service for example:
public class MyService {
public void process() {
try {
CustomerMessagesService customerMessagesService = new CustomerMessagesService();
String message = customerMessagesService.getMessage();
// another logic which can throw an exception
SpamCenterService spamCenterService = new SpamCenterService();
spamCenterService.sendAdvertise(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
This service calls from Scheduler each 1 second.
customerMessagesService return message with an advertisement text or throw an exception if this message contains illegal text. If customerMessagesService return success text - it to send to spamCenterService and if customerMessagesService throw an exception - it exception just logged. There is another logic which can throw exception between calls of these services. This exception logs too.
Now I want to create a unit test for this method. But I don't understand how to test the void method with try..catch block.
I create this:
public class MyServiceTest {
private MyService myService;
#Before
public void setUp() {
myService = new MyService();
}
#Test
public void process() {
myService.process();
}
}
But it is always a success because the process method doesn't throw exceptions.
How can I test this method?
EDIT
I find one solution but I am not sure about it.
public class MyServiceImpl implements MyService {
public void process() {
try {
doIt();
} catch (Exception e) {
e.printStackTrace();
}
}
public void doIt() throws Exception {
CustomerMessagesService customerMessagesService = new CustomerMessagesService();
String message = customerMessagesService.getMessage();
// another logic which can throw an exception
SpamCenterService spamCenterService = new SpamCenterService();
spamCenterService.sendAdvertise(message);
}
}
And test doIt() method in MyServiceImpl.
In short do the following:
Move object creation out of your method
Create mocks (with e.g. Mockito) and inject those
verify that the mocks were used as expected
A concrete example below:
public class MyService {
private CustomerMessagesService customerMessagesService;
private SpamCenterService spamCenterService;
//inject dependencies
public MyService(CustomerMessagesService customerMessagesService, SpamCenterService spamCenterService) {
this.customerMessagesService = customerMessagesService;
this.spamCenterService = spamCenterService;
}
public void process() {
try {
String message = customerMessagesService.getMessage();
// another logic which can throw an exception
spamCenterService.sendAdvertise(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class MyServiceTest {
private MyService myService;
// mock dependencies with Mockito
private CustomerMessagesService customerMessagesService = Mockito.mock(CustomerMessagesService.class);
private SpamCenterService spamCenterService = Mockito.mock(SpamCenterService.class);
#Before
public void setUp() {
myService = new MyService(customerMessagesService, spamCenterService);
}
#Test
public void process() {
myService.process();
Mockito.verify(customerMessagesService).getMessage();
ArgumentCaptor<String> messageCaptor = ArgumentCaptor.forClass(String.class);
Mockito.verify(spamCenterService).sendAdvertise(messageCaptor.capture());
assertThat(messageCaptor.getValue(), is(nullValue()));
}
#Test
public void processWithSpecificCustomerMessageServiceBehaviour() {
Mockito.given(customerMessagesService.getMessage()).willReturn("expectedString");
myService.process();
ArgumentCaptor<String> messageCaptor = ArgumentCaptor.forClass(String.class);
Mockito.verify(spamCenterService).sendAdvertise(messageCaptor.capture());
assertThat(messageCaptor.getValue(), is("expectedString"));
}
#Test
public void processCatchExceptions() {
Mockito.given(customerMessagesService.getMessage()).willThrow(new Exception("Bad message"));
myService.process();
// if exception is thrown then the code should not reach spamCenterService.sendAdvertise()
Mockito.verify(spamCenterService, Mockito.never()).sendAdvertise(Mockito.anyString());
}
}
Note that you can also setup mocks to throw specific exceptions or return specific values so that you can test all possible scenarios.
I have service method which return DefferedResult<Foo> in few seconds, but I need my code will wait until that method finish and return deferred result with set result.
Here is sample code:
#Service
public class FooService {
// ...
public DeferredResult<Foo> fetchFoo(long id) throws InterruptedException {
DeferredResult<Foo> fooDeferredResult = new DeferredResult<>();
concurrentMap.put(id, fooDeferredResult);
return fooDeferredResult;
}
// this you can figure out as some handler or scheduler which receive messages and is called
public void anotherMethod(Foo foo) {
DeferredResult<Foo> remove = concurrentMap.remove(foo.getId());
remove.setResult(foo);
}
// ...
}
and I want call it in another service:
#Service
public class AnotherService {
#Autowired
FooService fooService;
public Foo bar(long id) {
// some logic
Foo foo = fooService.fetchFoo(id).getResult();
// another logic which depends on received foo
// there I need wait for result of fetchFoo method
return foo;
}
}
Can you tell me please how to ensure this behaviour? Thank you in advice.
You can use CountDownLatch for synchronize. Example:
public class Main {
public static void main(String[] args) throws InterruptedException {
System.out.println(1);
CountDownLatch latch = new CountDownLatch(1);
getResult()
.setResultHandler(result -> {
System.out.println(2 + " " + result);
latch.countDown();
});
latch.await();
System.out.println(3);
}
public static DeferredResult<String> getResult() {
DeferredResult<String> result = new DeferredResult<>();
new Thread(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
result.setResult("Hello");
})
.start();
return result;
}
}
I am using Mockito/PowerMockito APIs to mock some objects for junit cases.
In the example given below, I want to create a mock object of class C (returned by Utils.getC()). Also I want to use same mock object of C in B.execute(), and not a new object. Is there a way I can achieve this? Please help. [Update - Thanks Lino for answering this. I have edited the code given below.]
However, this works for static methods only. I am not able to mock instance method D.displayMessage() (invoked from A.execute() and B.execute()).
#PrepareForTest(mock.Utils.class)
#RunWith(PowerMockRunner.class)
public class TestMock {
private static C c;
private static D d;
#BeforeClass
public static void runOnceBeforeClass() {
try {
System.out.println("#BeforeClass - runOnceBeforeClass");
PowerMockito.mockStatic(Utils.class);
c = Mockito.mock(C.class);
System.out.println("c = " + c);
PowerMockito.doReturn("Hello!!").when(c).displayMessage();
Answer<Void> answer = new Answer() {
public Void answer(InvocationOnMock invocation) {
System.out.println("I can perform!");
return null;
}
};
PowerMockito.doAnswer(answer).when(c).perform();
PowerMockito.when(Utils.getC()).thenReturn(c);
Answer<Void> answer1 = new Answer() {
public Void answer(InvocationOnMock invocation) {
System.out.println("I can utilize!");
return null;
}
};
PowerMockito.doAnswer(answer1).when(Utils.class);
Utils.utilize();
Answer<Void> answer2 = new Answer() {
public String answer(InvocationOnMock invocation) {
System.out.println("I can run with params!");
return null;
}
};
PowerMockito.doAnswer(answer2).when(Utils.class);
Utils.runWithParams(Mockito.anyString(), Mockito.anyInt(), Mockito.any());
d = PowerMockito.mock(D.class);
PowerMockito.when(d.displayMessage()).thenReturn("D: I can display!");
PowerMockito.whenNew(D.class).withNoArguments().thenReturn(d);
} catch (Exception ex) {
ex.printStackTrace();
}
}
#AfterClass
public static void runOnceAfterClass() {
System.out.println("#AfterClass - runOnceAfterClass");
}
#Before
public void runBeforeTestMethod() {
System.out.println("#After - runBeforeTestMethod");
}
#After
public void runAfterTestMethod() {
System.out.println("#After - runAfterTestMethod");
}
#Test
public void testExecution() {
System.out.println(Utils.getC().displayMessage());
A a = new A();
a.execute();
}
}
class A {
public void execute() {
System.out.println("executing A");
B b = new B();
b.execute();
System.out.println(new D().displayMessage());
}
}
class B {
public void execute() {
System.out.println("executing B");
C c1 = Utils.getC();
System.out.println("c = " + c1.hashCode());
c1.perform();
Utils.utilize();
Utils.runWithParams("", 3, "2");
System.out.println(new D().displayMessage());
}
}
class C {
public String displayMessage() {
return "C: I can't display.";
}
public void perform() {
System.out.println("I can't perform.");
}
}
class D {
public String displayMessage() {
return "D: I can't display.";
}
}
class Utils {
public static C getC() {
return null;
}
public static void utilize() {
System.out.println("I can't unitilize.");
}
public static String runWithParams(String s, Integer i, Object o) {
System.out.println("I can't run with params.");
return "abc";
}
}
If you are trying to reuse the mocked object of C, for the static method call inside execute() method of B , the same mocked object can be reused.