Unable to test #Scheduled annotation through the Impl class - spring

I’m trying to test my spring #Scheduled method with Junit regarding how often it runs and since it can’t be annotated in the Interface, i have the annotation in the Impl class. But when i have the #SpyBean private FooImpl fooImpl; along with #Autowired private Foo foo; in the test class, it gives me a BeanNotOfRequiredTypeException. Any suggestions on how to get rid of the exception and be able to run my test?

Related

(SpringBoot) Problem in JunitTest can't use #Mockbeans on a list of subclasses

I have a specific problem in my unit tests.
in my service I use a #Autowired to get a list of all my subclasses.
Example :
#Autowired
List<MotherRepositoryClass> repositories;
So in my service I have a list of all subclasses that are automatically instantiated and it's working fine.
However I want to do the same thing to mock them in my tests to avoid adding for each class an attribute. Unfortunately the #Mockbean annotation is only available for one bean.
For now, the only track I found was to put the same attribute #Autowire with my MotherClass and mocking them inside a #BeforeEach. However the Mockito.mock() is not the same as the #Mockbean as it only mock the provided instance so the service instantiate a new Bean when created.
EDIT 1 : I may do something with the ApplicationContext

MockBean and MyBatis Mapper not working together (as they did before Spring Boot 2.2.7)

I am using MyBatis Spring Boot Starter version 2.1.3. Ever since moving to Spring Boot 2.2.7 (I've also tried 2.2.8 and 2.3.1 with the same results), I've had a problem using the MockBean annotation to mock a MyBatis interface (e.g. DAO). Let's say I have an interface like this one:
#Mapper
#Repository
public interface OrderDAO {
int insertOrder(#Param("order") Order order);
}
I'd like to execute an integration test and mock this mapper within my OrderService that contains a field of type OrderDAO.
My integration test is annotated with #SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) and contains this field:
#MockBean
private OrderDAO orderDAO;
When I run a test such as this and look at what the references to the OrderDAO objects are, in my integration test I see this:
com.example.dao.OrderDAO$MockitoMock$1819884459
But inside my OrderService class the field is this:
com.sun.proxy.$Proxy179 (org.apache.ibatis.binding.MapperProxy#37d9310e)
So, calls to Mockito.verify obviously don't work because my mock has not been injected into my OrderService class. Now, very oddly, I found that adding this code makes everything work:
#TestConfiguration
static class MockConfig {
#Bean
public OrderDAO orderDAO() {
return Mockito.mock(OrderDAO.class);
}
}
Adding this nested class along with adding the ContextConfiguration annotation on the integration test class, and now the object that gets injected into the OrderService class is the MockitoMock -- the same object that is referenced by the MockBean annotated field in the test class. I didn't have to do this with Spring Boot 1.2.6 and earlier and I couldn't find any reference to a change that would have caused this (although perhaps I didn't search long enough).
So, I am wondering if I am doing something incorrectly, or, am I missing something I should be doing? It seems like this should just work like it did before, which the need for this extra nested TestConfiguration class. Appreciate any insights anyone can provide. Thanks.
As mentioned by ave in the comments, I had to add the name to the mock bean annotation to get it to work
#MockBean(name = "orderDAO")
private OrderDAO orderDAO;

How to Mock Spring Boot Application Context In Unit Testing

I Have a Source class which has a dependency Of type Application Context. Using this we are achieving polymorphism. How to unit test this class. I'm using Spring boot application.
#Autowired
ApplicationContext applicationContext;
String beanName= "employeeImpl";
applicationContext.getBean(beanName, Employee.class);
For situations where you are trying to mock a hard-to-mock class, consider using a wrapper class (i.e. the Adapter/Wrapper pattern). For example, one might create new class, ApplicationContextAdapter that is auto wired into your class under test as a class that is easy to mock. This new class would internally autowire the actual ApplicationContextinstance and might have a getApplicationContext() method to get the wrapped instance.
That being said, I agree with #DarrenForsythe that you don’t shouldn’t autowire this class.

Spring Boot Test - Mocking A Handler Bean That Is Placed Deep In The Chain Of Responsibility

This should happen quite often:
RestController -> SomeClass -> SomeOtherClass -> YetAnotherClass and so on...
In my specific case there is a chain of responsibility which is injected to a rest controller. Each class is injected to it's previous class in the above chain.
I have implemented this with spring boot and I'm trying to test the REST resource. I want to Mock the "YetAnotherClass" so that when I send a request with MockMvc I can verify that something has happened in the mock object.
The problem is if I use #MockBean to mock YetAnotherClass then I have to inject it to SomeOtherClass. I have tried to inject it with #TestConfiguration but it seems that the Mock object injection doesn't work this way when the request is sent through MockMvc and the mock object is nested deep inside a chain such as above. (The original bean is injected not the mock one)
I know that JMockit mocks every instance of a class so it would solve my problem. But Spring boot defaults to Mockito and I prefer to avoid inconsistencies.
How can I implement such a test scenario?
I've run into a lot of annoyance using Mockito's annotation config setup when setting up Spring JUnit text fixtures.
I've found the way I like mocking beans with external integrations like this this by essentially having a separate MockObjectsConfig class with the mock objects I want using the standard Spring Context Configuration, and then import it alongside my real test config:
#Configuration
public class MockObjectsConfig {
#Bean
public YetAnotherClass yetAnotherClass() {
Mockito.mock(YetAnotherClass.class); // and add any thenReturns, answers, etc. here
}
... More mock beans...
}
Then include it in your test like so:
#RunWith(SpringRunner.class)
#ContextConfiguration(classes = { MyRealConfigClass.class, MockObjectsConfig.class)
public class MyJunitTest {
#Autowired
private RestController restController;
}
You can also annotate your mock bean with #Profile and test with #ActiveProfiles if you need to prevent a conflict there.
This way your mock YetAnotherClass will get injected into your context like all your other beans -- no relying on, mixing, and fiddling around with Mockito and other library annotations.

spring integration test fail to load context "Another resource already exists with name dataSource"

I am using test annotation introduced in spring-boot 1.4.3 for my integration tests
#RunWith(SpringRunner.class)
#SpringBootTest
public class MyServiceIT { }
According to documentation, test context is cached and reused to speed up integration tests. This behavior is what I want since it takes significant amount of time to initialize application context. My failsafe plugin is configured with
<forkCount>1</forkCount>
<reuseForks>true</reuseForks>
to allow integration tests to run in the same process to take advantage of application context caching.
Recently, I wrote a integration test used #MockBean annotation to mock behavior for some beans.
#RunWith(SpringRunner.class)
#SpringBootTest
public class AnotherServiceIT {
#MockBean
SomeService service1
}
While the test runs fine on it's own, when running through maven verify, multiple integration tests fails with the error message
javax.naming.NamingException: Another resource already exists with
name dataSource - pick a different name
If I skip this particular test with JUnit #Ignore annotation, everything goes back to normal.
This behavior seems to indicate that using #MockBean changes the caching behavior, and each test attempts to create its own datasource. I should also mention that I am using an AtomikosDataSourceBean created through XADataSourceAutoConfiguration.
How can I overcome this issue so my integration test can still use cached context and use #MockBean at the same time?
Hmm, does SomeService relate to your Datasource in any way?
Because your context is cached and #MockBean does the following:
used to add mocks to a Spring ApplicationContext ... Any existing single bean of the same type defined in the context will be replaced by the mock,
and
If there is more than one bean of the requested type, qualifier metadata must be specified at field level:
#RunWith(SpringRunner.class)
public class ExampleTests {
#MockBean
#Qualifier("example")
private ExampleService service;
Edit:
So if your SomeService is an implementation of a DataSource try adding a Qualifier. If SomeService has a DataSource in it, and you need to access some methods in it, you could try to use #Mock and specify the any objects that need to be returned either through their own mock or autowire.
#Mock
SomeService someService;
#Mock
SomeDependency mockDependency;
#Autowired
OtherDependency realDependency;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
doReturn(mockDependency).when(someService).getSomeDependency();
doReturn(realDependency).when(someService).getOtherDependency();
}

Resources