Constructor injection with mocked object which has to set mocked value in constructor - mockito

I'm trying to mock a class FooB, which has another component FooA injected via constructor injection. My problem is, that in constructor FooB a value from injected component FooA has to be set. My problem I don't know the way how to mock FooA. Usually I would do something like in the commented out code in a #BeforeAll and mock the value with Mockito.when. But at this stage FooB is already initialized.
#ExtendWith(SpringExtension.class)
#ContextConfiguration(classes = { FooB.class })
class FooTest {
#MockBean
private FooA fooA;
#Autowired
private FooB fooB;
// #BeforeAll
// void initMocks() {
// when(fooA.getFoo()).thenReturn("foo");
// }
}
#Component
public class FooB {
private final String foo;
public FooB(final FooA fooA) {
this.foo = fooA.getFoo(); // <- how do I get the mocked value in here?
}
}
#Component
public class FooA {
private String foo;
public String getFoo() {
return foo;
}
public void setFoo(final String foo) {
this.foo = foo;
}
}

The below code could solve what you are trying to do (Edit : Added both a test case that uses #SrringBootTest and without it as well)
If not using SpringBoot
#ExtendWith(SpringExtension.class)
#ContextConfiguration(classes = {FooB.class, FooTest.TestConfig.class})
class FooTest {
#Autowired
private FooB fooB;
#TestConfiguration
public static class TestConfig {
#Bean
FooA getFooA(){
FooA fooA = Mockito.mock(FooA.class);
when(fooA.getFoo()).thenReturn("foo from test");
return fooA;
}
}
#Test
void testFooB() {
assertEquals("foo from test", fooB.getFoo());
}
}
If using SpringBoot
#SpringBootTest
class FooTest {
#Autowired
private FooB fooB;
#TestConfiguration
public static class TestConfig {
#MockBean
private FooA fooA;
#PostConstruct
void initMocks() {
when(fooA.getFoo()).thenReturn("foo from test");
}
}
#Test
void testFooB() {
assertEquals("foo from test", fooB.getFoo());
}
}

Related

Stub all the method call including a method call inside it, from another class using mockito

How to stub a System.currentTimeMillis() in the classB from classA?
Class A:
public classA {
#Test public void timeTest() {
PowerMockito.mockStatic(System.class);
PowerMockito.when(System.currentTimeMillis()).thenReturn(10L);
B.testPowerMock(); }
}
Class B:
public class B {
public static void testPowerMock() {
System.out.println(System.currentTimeMillis());
}
}

How to get beans with custom annotation via ArC in quarkus?

I want to find beans at runtime depending on user input, so using io.quarkus.arc.Arc.
However, I cannot figure out how to get beans with custom annotation in a reasonable way. Only got something working by implementing the annotation interface like:
InstanceHandle<Service> instanceHandleA = Arc.container()
.instance(Service.class, new SupportsJobTypeImpl(JobType.A));
InstanceHandle<Service> instanceHandleB = Arc.container()
.instance(Service.class, new SupportsJobTypeImpl(JobType.B));
class SupportsJobTypeImpl implements SupportsJobType {
JobType requestedJobType;
public SupportsJobTypeImpl(JobType requestedJobType) {
this.requestedJobType = requestedJobType;
}
#Override
public JobType value() {
return requestedJobType;
}
#Override
public Class<? extends Annotation> annotationType() {
return SupportsJobType.class;
}
}
Is there a way to get instanceHandleA, instanceHandleB with less cumbersome verbose code like SupportsJobTypeImpl?
Background info about my test code:
public enum JobType {
A,B
}
#Qualifier
#Retention(RUNTIME)
#Target({METHOD, FIELD, PARAMETER, TYPE})
public #interface SupportsJobType {
JobType value();
}
#ApplicationScoped
#SupportsJobType(JobType.A)
public class ServiceForA extends Service {
}
#ApplicationScoped
#SupportsJobType(JobType.B)
public class ServiceForB extends Service {
}
UPDATE: Tried to get it working by including SupportsJobTypeImpl in the SupportsJobType annotation interface (like in the example from https://docs.jboss.org/cdi/api/2.0/javax/enterprise/util/AnnotationLiteral.html):
#Qualifier
#Retention(RUNTIME)
#Target({METHOD, FIELD, PARAMETER, TYPE})
public #interface SupportsJobType {
JobType value();
public abstract class Literal extends AnnotationLiteral<SupportsJobType> implements SupportsJobType {
JobType requestedJobType;
public Literal() {
}
#Override
public JobType value() {
return requestedJobType;
}
#Override
public Class<? extends Annotation> annotationType() {
return SupportsJobType.class;
}
}
}
however, I get no bean instance from ArC by:
InstanceHandle<Service> instanceHandleA = Arc.container().instance(Service.class, new SupportsJobType.Literal() {
public JobType value() {
return JobType.A;
}
});
UPDATE2: also not working:
#Qualifier
#Retention(RUNTIME)
#Target({METHOD, FIELD, PARAMETER, TYPE})
public #interface SupportsJobType {
JobType value();
class Literal extends AnnotationLiteral<SupportsJobType> implements SupportsJobType {
JobType requestedJobType;
public Literal(JobType requestedJobType) {
this.requestedJobType = requestedJobType;
}
#Override
public JobType value() {
return requestedJobType;
}
#Override
public Class<? extends Annotation> annotationType() {
return SupportsJobType.class;
}
}
}
I get no bean instance from ArC by:
InstanceHandle<Service> instanceHandleA = Arc.container().instance(Service.class, new SupportsJobType.Literal(JobType.A));
As far as I can tell, what you're doing is exactly what you should do. It is idiomatic for implementations of annotation types to be nested in the annotation type itself, be called Literal and extend the AnnotationLiteral class. For example (writing from memory):
#Qualifier
#Retention(RUNTIME)
#Target({METHOD, FIELD, PARAMETER, TYPE})
public #interface SupportsJobType {
JobType value();
class Literal extends AnnotationLiteral<SupportsJobType> implements SupportsJobType {
private final JobType value;
public Literal(JobType value) {
this.value = value;
}
#Override
public JobType value() {
return value;
}
}
}
Turns out I was stumbling over a small detail like mentioned in https://stackoverflow.com/a/66980506/753724
which means I simply had to add #Unremovable to beans resulting in:
#ApplicationScoped
#Unremovable
#SupportsJobType(JobType.A)
public class ServiceForA extends Service {
}
#ApplicationScoped
#Unremovable
#SupportsJobType(JobType.B)
public class ServiceForB extends Service {
}
With the slightly adapted Annotation class (only new static method):
#Qualifier
#Retention(RUNTIME)
#Target({METHOD, FIELD, PARAMETER, TYPE})
public #interface SupportsJobType {
JobType value();
class Literal extends AnnotationLiteral<SupportsJobType> implements SupportsJobType {
JobType requestedJobType;
public Literal(JobType requestedJobType) {
this.requestedJobType = requestedJobType;
}
public static Literal of(JobType value) {
return new Literal(value);
}
#Override
public JobType value() {
return requestedJobType;
}
#Override
public Class<? extends Annotation> annotationType() {
return SupportsJobType.class;
}
}
}
the beans were found as expected by:
InstanceHandle<Service> instanceHandleA = Arc.container().instance(Service.class, SupportsJobType.Literal.of(JobType.A));
InstanceHandle<Service> instanceHandleB = Arc.container().instance(Service.class, SupportsJobType.Literal.of(JobType.B));

Springboot mockito mock a field

I want to mock the TreeMap in Service class, I tried to mock using TreeMap<String, String> requestsMap = Mockito.mock(TreeMap.class); But the map is getting null at runtime.
#RunWith(SpringRunner.class)
#SpringBootTest
#WebAppConfiguration
public class ServiceTest {
#InjectMocks
private Service service;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test() {
TreeMap<String, String> requestsMap = Mockito.mock(TreeMap.class);
}
}
#Service
public class Service {
private TreeMap<String, String> requestsMap = null;
}
Your Service class doesn't actually do anything but declare and initialize the requestMap to null. Also, your test method doesn't do anything other than declare a mock requestMap.
In addition to the code you have, write a method in the Service that uses the request map and just declare/autowire the requestMap. In your test, use the #Mock annotation on a declaration of your mock requestMap. Finally, use the mocked requestMap in your test.
For example:
#RunWith(SpringRunner.class)
#SpringBootTest
#WebAppConfiguration
public class ServiceTest {
#Mock
TreeMap<String, String> requestsMap;
#InjectMocks
private Service service;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test() {
when(requestMap.get("foo")).thenReturn("bar");
String result = service.doSomething();
assertEquals(result, "bar");
}
}
#Service
public class Service {
#Autowired
private TreeMap<String, String> requestsMap;
public String doSomething() {
return requestMap.get("foo");
}
}

#SpringIntegrationTest annotation does not load context as expected

Normally, when I use #SpringBootTest I get the full context of beans. I can the #Autowire all kinds of beans that are available after the application has started.
Now, in the scope of spring-integration-test libary, the #SpringIntegrationTest does not do this.
As the testing module promises, you can use
#Autowired
private MockIntegrationContext mockIntegrationContext;
However, after inspecting the bean map on that instance, I found out there are no beans!
Example test:
#ActiveProfiles("test")
#RunWith(SpringRunner.class)
#SpringIntegrationTest
public class AppTest {
#Autowired
private MockIntegrationContext mockIntegrationContext;
#Test
public void contextLoads() {
// put breakpoint to inspect field
System.out.println(mockIntegrationContext);
}
}
When I however run the following code, I get a complete context:
#ActiveProfiles("test")
#RunWith(SpringRunner.class)
#SpringBootTest
public class App2Test {
#Autowired
private ListableBeanFactory beanFactory;
#Test
public void contextLoads() {
Assert.isTrue(beanFactory.getBeanDefinitionCount() > 0)
}
}
Why is that? How can I achieve a similar result with spring-integration-test?
Reading materials: https://docs.spring.io/spring-integration/docs/current/reference/html/testing.html
They are independent annotations; you need both.
EDIT
This works fine for me:
#RunWith(SpringRunner.class)
#SpringBootTest
#SpringIntegrationTest
public class So52297757ApplicationTests {
#Autowired
private MockIntegrationContext mockIntegrationContext;
#Autowired
private String foo;
#Test
public void contextLoads() {
System.out.println(foo);
System.out.println(mockIntegrationContext);
}
}
and
#SpringBootApplication
public class So52297757Application {
public static void main(String[] args) {
SpringApplication.run(So52297757Application.class, args);
}
#Bean
public String foo() {
return "foo";
}
}
and
foo
org.springframework.integration.test.context.MockIntegrationContext#1de5f0ef

Is threre any way to ues override method in anonymous class on Groovy #CompileStatic annotation

Is threre any way to ues override method in anonymous class on Groovy #CompileStatic annotation?
groogy source
import groovy.transform.CompileStatic;
interface HelloWorld {
public void greet();
}
class HelloWorldAnonymousClassesParents {
public void hi() {
println "hi"
}
}
#CompileStatic
public class HelloWorldAnonymousClasses extends HelloWorldAnonymousClassesParents {
public void hi() {
System.out.println("hihi ");
}
public void sayHello() {
HelloWorld spanishGreeting = new HelloWorld() {
public void greet() {
hi() //<- here [Static type checking] - Reference to method is ambiguous error
System.out.println("spanishGreeting");
}
};
spanishGreeting.greet();
hi()
}
}
def myApp = new HelloWorldAnonymousClasses();
myApp.sayHello();
Same source in java run well
java source
package org.octopus;
class HelloWorldAnonymousClassesParents {
public void hi() {
System.out.println("hi ");
}
}
interface HelloWorld {
public void greet();
}
public class Test extends HelloWorldAnonymousClassesParents{
public void hi() {
System.out.println("hihi ");
}
public void sayHello() {
HelloWorld spanishGreeting = new HelloWorld() {
public void greet() {
hi();
System.out.println("spanishGreeting");
}
};
spanishGreeting.greet();
hi();
}
public static void main(String... args) {
Test myApp = new Test();
myApp.sayHello();
}
}
How can I avoid that error with #CompileStatic annotation?
You can write it as a closure. This implies an as HelloWorld and as the interface only has one method groovy can deduct this.
HelloWorld spanishGreeting = {
hi()
System.out.println("spanishGreeting");
}
above code is groovy 2.3; with earlier groovy 2 versions it needs an explicit cast like
def spanishGreeting = {/*...*/} as HelloWorld

Resources