Jmockit and #PostConstruct bean - java

I have created a bean with method that I want to test. Unfortunately it's a bean with a PostConstruct annotation in it. I don't want to call the PostConstruct method.
How can I do this?
I've tried 2 different ways (as shown in the example below) but none working; init() still gets called.
Can someone please give me a detailed example of how to do this?
DirBean.java
#Singleton
#Startup
public class DirBean implements TimedObject {
#Resource
protected TimerService timer;
#PostConstruct
public void init() {
// some code I don't want to run
}
public void methodIwantToTest() {
// test this code
}
}
MyBeanTest.java
public class MyBeanTest {
#Tested
DirBean tested;
#Before
public void recordExpectationsForPostConstruct() {
new Expectations(tested) {
{
invoke(tested, "init");
}
};
}
#Test
public void testMyDirBeanCall() {
new MockUp<DirBean>() {
#Mock
void init() {
}
};
tested.methodIwantToTest();
}
}
MyBeanTest2.java (WORKS)
public class MyBeanTest2 {
#Tested
DirBean tested;
#Before
public void recordExpectationsForPostConstruct() {
new MockUp<DirBean>() {
#Mock
void init() {}
};
}
#Test
public void testMyDirBeanCall() {
tested.methodIwantToTest();
}
}
MyBeanTest3.java (WORKS)
public class MyBeanTest3 {
DirBean dirBean = null;
#Mock
SubBean1 mockSubBean1;
#Before
public void setupDependenciesManually() {
dirBean = new DirBean();
dirBean.subBean1 = mockSubBean1;
}
#Test
public void testMyDirBeanCall() {
dirBean.methodIwantToTest();
}
}
MyBeanTest4.java (FAILS with NullPointerException on invoke())
public class MyBeanTest4 {
#Tested
DirBean tested;
#Before
public void recordExpectationsForCallsInsideInit() {
new Expectations(tested) {
{
Deencapsulation.invoke(tested, "methodCalledfromInit", anyInt);
}
};
}
#Test
public void testMyDirBeanCall() {
tested.methodIwantToTest();
}
}

Move definition of MockUp type to #Before method:
public class MyBeanTest {
#Tested
DirBean tested;
#Before
public void recordExpectationsForPostConstruct() {
new MockUp<DirBean>() {
#Mock
void init() {
}
};
}
#Test
public void testMyDirBeanCall() {
tested.methodIwantToTest();
}
}

Related

Why can't mock static method in Spring condition

this is my code.
class ACondition extends SpringBootConditoin {
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
if (Config.isA()) {
return new ConditionOutcome(true, "ok");
} else {
return new ConditionOutcome(false, "error");
}
}
}
class BCondition extends SpringBootConditoin {
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
if (Config.isA()) {
return new ConditionOutcome(false, "error");
} else {
return new ConditionOutcome(true, "ok");
}
}
}
#Service
#Conditional(ACondition.class)
class APolicy implements Policy {
...
}
#Service
#Conditional(BCondition.class)
class BPolicy implements Policy {
...
}
class PolicyManager {
#Autowired
#Getter
List<Policy> policyList;
...
}
the default value of Config.isA() is true.
I want to make Config.isA() to return false. so I use Mockito.mockstatic.
#Autowired
PolicyManager manager;
#Test
public void get_B_policy() {
try(MockedStatic<Config> mocked = Mockito.mockStatic(Config.class) {
mocked.when(() -> Config.isA()).thenReturn(false);
List<Policy> policyList = manager.getPolicyList();
assertEquals(1, policyList.size()); // this is right
assertTrue(policyList.get(0) instanceof BPolicy); // this is not right
}
}
Why can't mock the online method?
by the way. If I test the BCondition class, the Config.isA() can be mocked. I can enter the branch which I want. It does not work only in conditional annotation.
Spring Context is already loaded by the time it is reaching the Test Case. Hence, Manager already has selected APolicy.
If you could move the static mock config before spring context loads, then it should match your expectations.
mocked.when(() -> Config.isA()).thenReturn(false);
One way of doing it is initialising the static Mock like below -
Junit4
#RunWith(SpringRunner.class)
#ContextConfiguration(classes = {PolicyManager.class, APolicy.class, BPolicy.class})
public class ConditionTest
{
#Autowired
PolicyManager manager;
static MockedStatic<Config> mocked = Mockito.mockStatic(Config.class);
#BeforeClass
public static void setup()
{
mocked.when(() -> Config.isA()).thenReturn(false);
}
#AfterClass
public static void clear()
{
mocked.close();
}
#Test
public void get_B_policy() {
List<Policy> policyList = manager.getPolicyList();
assertEquals(1, policyList.size()); // this is right
assertTrue(policyList.get(0) instanceof BPolicy); // should work now
}
}
Junit5
Please use Jupiter's annotations.
#Autowired
PolicyManager manager;
static MockedStatic<Config> mocked = Mockito.mockStatic(Config.class);
#BeforeAll
public static void setup() {
mocked.when(() -> Config.isA()).thenReturn(true);
}
#AfterAll
public static void clear() {
mocked.close();
}
#Test
public void get_B_policy() {
List<Policy> policyList = manager.getPolicyList();
assertEquals(1, policyList.size()); // this is right
assertTrue(policyList.get(0) instanceof BPolicy); // should work now
}

How to extract the common condition check in a class

If I have a class, where all methods should evaluate only if a boolean attribute is true, what is the best way to define it in terms of best practices?
Is there a way to replace the recurring isEnabled check in all the methods by a single check? The current form works, I'm looking for a way to improve it to not have isEnabled checked in all the methods.
#Singleton
public class SomeClass implements SomeInterface {
EventPublisher eventPubilsher;
boolean isEnabled;
#Inject
public SomeClass(final Decider decider, EventPublisher, eventPublisher) {
this.isEnabled = decider.isSomethingEnabled();
this.eventPublisher = eventPublisher;
}
#Override
public void method1() {
if(isEnabled){
eventPublisher.publishSomething1();
}
}
#Override
public void method2() {
if(isEnabled){
eventPublisher.publishSomething2();
}
}
#Override
public void method3() {
if(isEnabled){
eventPublisher.publishSomething3();
}
}
}
You can have implementation for enabled stuff, and one for disabled stuff. The disabled implementation won't do anything:
public class DisabledSomeClass implements SomeInterface {
#Override
public void method1() {
}
#Override
public void method2() {
}
#Override
public void method3() {
}
}
Enabled one will publish stuff:
public class EnabledSomeClass implements SomeInterface {
EventPublisher eventPublisher;
public EnabledSomeClass(EventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
#Override
public void method1() {
eventPublisher.publishSomething1();
}
#Override
public void method2() {
eventPublisher.publishSomething2();
}
#Override
public void method3() {
eventPublisher.publishSomething3();
}
}
Then extract the logic, if functionality is enabled in new factory class - SomeInterfaceFactory (probably not the best name, but you get the idea), it will return the correct implementation, depending on whether something is enabled.
public class SomeInterfaceFactory {
public static SomeInterface getInstance(Decider decider, EventPublisher eventPublisher) {
if (decider.isSomethingEnabled()) {
return new EnabledSomeClass(eventPublisher);
} else {
return new DisabledSomeClass();
}
}
}
This should work
#Singleton
public class SomeClass implements SomeInterface {
EventPublisher eventPubilsher;
boolean isEnabled;
#Inject
public SomeClass(final Decider decider, EventPublisher, eventPublisher) {
this.isEnabled = decider.isSomethingEnabled();
this.eventPublisher = eventPublisher;
}
#Override
public void method1() {
publish(ep->ep.publishSomething1());
}
#Override
public void method2() {
publish(ep->ep.publishSomething2());
}
#Override
public void method3() {
publish(ep->ep.publishSomething3());
}
private void publish(Consumer<EventPublisher> callback){
if(isEnabled) callback.accept(eventPublished);
}
}
A Runnable interface can receive a lambda without args and run a lambda function with run() method. So, you can create a method inside your Decider class and receive a Runnable as a parameter, like:
class Decider{
private boolean enabled;
//...
public void execute(Runnable runnable){
if(enabled) runnable.run();
}
}
And receive your Decider and do:
//...
EventPublisher eventPubilsher;
Decider decider;
#Inject
public SomeClass(final Decider decider, EventPublisher, eventPublisher) {
this.decider = decider;
this.eventPublisher = eventPublisher;
}
#Override
public void method1() {
Decider.execute(() -> eventPublisher.publishSomething1());
}
//...
You're locking the evaluation of the condition to the constructor. If you want any flexibility, you should pull it out.
public class SomeClass implements SomeInterface {
boolean isEnabled;
public SomeClass(EventPublisher, eventPublisher) {
//
}
public void addDecide(boolean value){
isEnabled = value;
}
boolean getEnabled(){
return isEnabled;
}
#Override
public void method3() {
if(getEnabled()){
eventPublisher.publishSomething3();
}
}
}
You can even go crazy and add a supplier:
public void addDecide(Supplier<Boolean> supplier){
supplier = supplier;
}
boolean getEnabled(){
return supplier.get();
}

Testing for class field with is share among methods

I have a Java class as follow
public class MyClass {
private final ShowFactory showFactory;
private SomeShow someShow;
public MyClass(ShowFactory showFactory) {
this.showFactory = showFactory;
startShow();
}
public void startShow() {
someShow = showFactory.createShow();
someShow.start();
}
public void showSomething() {
MagicBox magicBox = new MagicBox();
someShow.showSomething(magicBox);
}
public void stopShow() {
someShow.stop();
}
}
and trying to test showSomething method. Complete test file is as follow
public class MyClassTest {
private ShowFactory showFactory;
private SomeShow someShow;
#Before
public void setUp() {
showFactory = mock(ShowFactory.class);
someShow = mock(SomeShow.class);
when(showFactory.createShow()).thenReturn(someShow);
}
#Test
public void shouldStartShow() {
new MyClass(showFactory);
verify(someShow).start();
}
#Test
public void shouldShowSomething() throws Exception {
MagicBox magicBox = mock(MagicBox.class);
PowerMockito.whenNew(MagicBox.class).withAnyArguments().thenReturn(magicBox);
doNothing().when(someShow).showSomething(magicBox);
InOrder inOrder = inOrder(someShow);
MyClass myClass = new MyClass(showFactory);
myClass.showSomething();
inOrder.verify(someShow).start();
inOrder.verify(someShow).showSomething(magicBox);
}
#Test
public void shouldStopShow() {
MyClass myClass = new MyClass(showFactory);
myClass.stopShow();
verify(someShow).start();
verify(someShow).stop();
}
}
But test shouldShowSomething is failing with error Wanted but not invoked. Any thing I am missing here? Any suggestion?
It was simple fix. After reading through https://github.com/powermock/powermock/wiki/MockConstructor#quick-summary (thanks to #roby) turns out I was missing the #PrepareForTest annotation for the class.
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyClass.class)
public class MyClassTest {
...
}

Is there a "revert" to Spring #DependsOn annotation?

I need one Component to be initialized before another. With #DependsOn it would look something like this:
#Component("beana")
public class BeanA{
#PostConstruct
void init(){
// do smth
}
}
#Component("beanb")
#DependsOn("beana")
public class BeanB{
#PostConstruct
void init(){
// do smth
}
}
I now have to tell BeanB that it depends on the initialization of BeanA.
My problem is that I do not want BeanB to know about BeanAs existance (e.g, when BeanB is just publishing Events in an EventBus while initializing and BeanA handles these events). I would like to use an annotation at BeanA stating it should bei initialized before BeanB. So it would something like this:
#Component("beana")
#RequiredBy("beanb")
public class BeanA{
#PostConstruct
void init(){
// do smth
}
}
#Component("beanb")
public class BeanB{
#PostConstruct
void init(){
// do smth
}
}
Is there any Spring annotation or possibility to handle it like this?
I believe there is no out of the box spring annotation for this, but you can easily make your own one.
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface RequiredBy {
String[] value();
}
Then it is possible to iterate through all bean definitions and set dependsOn to that required bean.
#Component
public static class RequiredByBeanDefinitionPostProcessor implements BeanDefinitionRegistryPostProcessor {
#Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
for (String beanName : registry.getBeanDefinitionNames()) {
final BeanDefinition beanDefinition = registry.getBeanDefinition(beanName);
if (beanDefinition.getBeanClassName() == null) {
continue;
}
try {
final Class<?> beanClass = Class.forName(beanDefinition.getBeanClassName());
if (beanClass.isAnnotationPresent(RequiredBy.class)) {
final String[] dependantBeanNames = beanClass.getAnnotation(RequiredBy.class).value();
for (String dependantBeanName : dependantBeanNames) {
BeanDefinition dependantBeanDefinition = registry.getBeanDefinition(dependantBeanName);
dependantBeanDefinition.setDependsOn(beanName);
}
}
}
catch (ClassNotFoundException e) { throw new RuntimeException(e); }
}
}
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { }
}
And then use it like in you example:
#Component("beanA")
public static class BeanA {
#PostConstruct
private void init() {
System.out.println(this.getClass().getSimpleName());
}
}
#Component("beanB")
#RequiredBy({ "beanC", "beanA" })
public static class BeanB {
#PostConstruct
private void init() {
System.out.println(this.getClass().getSimpleName());
}
}
#Component("beanC")
#RequiredBy("beanA")
public static class BeanC {
#PostConstruct
private void init() {
System.out.println(this.getClass().getSimpleName());
}
}
=>
BeanB
BeanC
BeanA
You can use the #Order annotation as recommended by pvpkiran.
Your code would look something like this:
#Component("beana")
#Order(1)
public class BeanA{
#PostConstruct
void init(){
// do smth
}
}
#Component("beanb")
#Order(2)
public class BeanB{
#PostConstruct
void init(){
// do smth
}
}

Spring #Async method inside a Service

I have this service bean with a sync method calling the internal async method:
#Service
public class MyService {
public worker() {
asyncJob();
}
#Async
void asyncJob() {
...
}
}
The trouble is that the asyncJob is not really called in async way.
I found that this doesn't work because an internal call skips the AOP proxy.
So I try to self-refer the bean:
#Service
public class MyService {
MyService mySelf;
#Autowired
ApplicationContext cnt;
#PostConstruct
public void init() {
mySelf=(MyService)cnt.getBean("myService");
}
public void worker() {
mySelf.asyncJob();
}
#Async
void asyncJob() {
...
}
}
It fails. Again no async call.
So I tried to divide it in two beans:
#Service
public class MyService {
#Autowired
MyAsyncService myAsyncService;
public void worker() {
myAsyncService.asyncJob();
}
}
#Service
public class MyAsyncService {
#Async
void asyncJob() {
...
}
}
Fails again.
The only working way is to call it from a Controller Bean:
#Controller
public class MyController {
#Autowired
MyAsyncService myAsyncService;
#RequestMapping("/test")
public void worker() {
myAsyncService.asyncJob();
}
}
#Service
public class MyAsyncService {
#Async
public void asyncJob() {
...
}
}
But in this case it is a service job. Why I cannot call it from a service?
Found a really nice way to solve this (with java8) in the case where you have a lot of various things you want to both sync and async. Instead of creating a separate XXXAsync service for each 'synchronous' service, create a generic async service wrapper:
#Service
public class AsyncService {
#Async
public void run(final Runnable runnable) {
runnable.run();
}
}
and then use it as such:
#Service
public class MyService {
#Autowired
private AsyncService asyncService;
public void refreshAsync() {
asyncService.run(this::refresh);
}
public void refresh() {
// my business logic
}
public void refreshWithParamsAsync(String param1, Integer param2) {
asyncService.run(() -> this.refreshWithParams(param1, param2));
}
public void refreshWithParams(String param1, Integer param2) {
// my business logic with parameters
}
}
I solved the third method (divide it in two beans) changing the async method's access modifier to public:
#Service
public class MyService {
#Autowired
MyAsyncService myAsyncService;
public void worker() {
myAsyncService.asyncJob();
}
}
#Service
public class MyAsyncService {
#Async
public void asyncJob() { // switched to public
...
}
}
In my case, it was easier to remove the #Async annotation and use the taskExecutor directly to submit my task:
Before
#Async("taskExecutor")
private Future<U> executerEnAsync(
final T pInput) {
final U resultat = this.appelerBS(pInput);
return new AsyncResult<U>(resultat);
}
After
#Autowired
private AsyncTaskExecutor taskExecutor;
private Future<U> executerEnAsync(
final T pInput) {
final Future<U> future = taskExecutor.submit(new Callable<U>() {
#Override
public U call() {
final U resultat = appelerBS(pInput);
return resultat;
}
});
return future;
}

Categories