Integration Test Data Set Up in Spring Boot - spring-test

Here is my test class
#SpringBootTest
#ActiveProfiles("test")
public MyTest {
...
#Before
public void init() {
System.out.println(":::: --- start init() ---");
...
}
...
}
Strange enough, the init() won't run for some reason. If I change the #Before to #BeforeAll and the method to static, the init() will run. A problem is that those data set up code doesn't run inside a static method and I can't change all of them to run inside a static block. For now, I have the following code in each test method to overcome the issue
if(list.size() == 0)
init();
I am wondering why the #Before won't run. Any advice?

In JUnit 5, #BeforeEach and #BeforeAll annotations are the equivalents for #Before and #BeforeClass in JUnit 4.
#Before is a JUnit 4 annotation, while #BeforeAll is a JUnit 5 annotation. You can also see this from the imports org.junit.Before and org.junit.jupiter.api.BeforeAll.
Also, the code marked #BeforeEach is executed before each test, while #BeforeAll runs once before the entire test fixture.
To be able to run #BeforeAll on a non-static method you can change the lifecycle of the the test instance with:
#TestInstance(TestInstance.Lifecycle.PER_CLASS)
You have to be careful though, since the test class instance is now only created once, and not once per test method. If your test methods rely on state stored in instance variables, you may now need to manually reset the state in #BeforeEach or #AfterEach lifecycle methods.

Related

why can't my spring-cloud-stream mockito test Autowire my Processor?

I'm trying to create tests for my spring-cloud-stream project. I've created my own BizSyncProcessor interface instead of using the default Processor, which seems to be in all the documentation. I've done this kind of project before with tests, but can't remember if I used mockito at the same time, so I'm wondering if that's the issue, because I'm doing #RunWith(MockitoJUnitRunner.class) instead of #RunWith(SpringRunner).
I also had similar problems when building the actual app, before I included the rabbit implementation as a dependency in maven.
IntelliJ flags an error on the #Autowired BizSyncProcessor saying 'no Beans of type 'BizSyncProcessor' could be found. However I'm able to run the test, so it compiles, but then bizSyncProcessor is null when running the test.
I'm including mockito because the handler that listens for the message makes a call to another service (the SFISClient), so I'm mocking out that call.
Here's my test:
#RunWith(MockitoJUnitRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#EnableAutoConfiguration
#Configuration
#EnableBinding(BizSyncProcessor.class)
public class UpdatedBusinessHandlerTest {
#Autowired
private BizSyncProcessor bizSyncProcessor;
#Autowired
private MessageCollector messageCollector;
#Mock
SFISClient sfisClient;
#InjectMocks
UpdatedBusinessHandler updatedBusinessHandler;
#Test
public void testWiring() throws Exception {
UpdatedBusinessAlert updatedBusinessAlert = new UpdatedBusinessAlert();
updatedBusinessAlert.setBusinessId(UUID.randomUUID());
Message<UpdatedBusinessAlert> updatedBusinessAlertMessage = MessageBuilder.withPayload(updatedBusinessAlert).build();
bizSyncProcessor.writeUpdatedBusinessIds().send(updatedBusinessAlertMessage);
Message<BusinessFlooringSummary> businessFlooringSummaryMessage = (Message<BusinessFlooringSummary>) messageCollector.forChannel(bizSyncProcessor.writeFlooringSummaries()).poll();
BusinessFlooringSummary businessFlooringSummary = businessFlooringSummaryMessage.getPayload();
assertNotNull(businessFlooringSummary);
}
}
The #SpringBootTest and everything Spring-based are not going to work in your case because you don't use #RunWith(SpringRunner). There is just nothing what can trigget those Spring hooks.
On the other hand there is no reason to use a MockitoJUnitRunner. You simply can rely on the #MockBean instead for your SFISClient: https://docs.spring.io/spring-boot/docs/2.1.1.RELEASE/reference/htmlsingle/#boot-features-testing-spring-boot-applications-mocking-beans

Mockito initMocks with #BeforeClass

Is there any reason why everybody uses #Before instead of #BeforeClass with initMocks? In my case I have only one method call in setup method and that is MockitoAnnotations.initMocks. #BeforeClass is even faster.
#BeforeClass, as the name suggest is run after class is loaded and no object exist. So all variable which you initialize need to be static. So, if you want to reuse this static variable in all testcases, as base setup input data, then you can do ahead with using #BeforeClass.
#Before is useful, then you want to reset the data before each test case gets called, so you are sure, anyone changing the input base data, does not impact the with what the next test is called.
coming to initmock, you can do via #Mock, #InjectMocks and using #RunWith(MockitoJUnitRunner.class)
#RunWith(MockitoJUnitRunner.class)
public class SampleTest {
#InjectMocks
private ClassA classA;
#Mock
private ClassB classB
// #BeforeClass and other test methods
}
In above code,
1. Instance of ClassA will be created
2. Mock object of ClassB will be created
3. classB will be injected in ClassA object created in step 1

how not invoke specific method on spring batch

Is there a way with mockito to test my batch and tell to not invoke specific method that the process call MyService.class, inside that service i got some business logic in a specific method that i don't want him to invoke is that possible? I was sure that doing the doReturn will ignore my method (the method is public) but still get call.
#Autowired
private JobLauncherTestUtils jobLauncherTestUtils;
#Autowired
private MyRepo myRepoRepository;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testJob() throws Exception {
doReturn(true).when(spy(MyService.class)).validationETPer(any(Object.class), anyChar());
doReturn(true).when(spy(MyService.class)).validationMP(any(Object.class),anyChar());
JobExecution execution = jobLauncherTestUtils.launchJob();
assertEquals(execution.getStepExecutions().size(), 1);
for (StepExecution stepExecution : execution.getStepExecutions()) {
assertEquals(3, stepExecution.getReadCount());
assertEquals(3, stepExecution.getWriteCount());
}
assertEquals(ExitStatus.COMPLETED.getExitCode(), execution.getExitStatus().getExitCode());
assertEquals(2, myRepoRepository.count());
}
This line does not what you believe it does:
doReturn(true).when(spy(MyService.class)).validationETPer(any(Object.class), anyChar());
spy(MyService.class) creates a new instance of MyService and spies on it. Of course, since you never use that instance, it's completely useless. There is an instance that is spied on, but you didn't store it anywhere, you didn't put it anywhere and so nobody will ever use it.
That line does not spy on every MyService in existence, as you seem to believe, it creates one concrete instance of MyService and spies on that. Obviously, that's not what you want here - you want to spy on the instance that is actually used in your code.
What you probably wanted to do, is more something like this...
MyService mySpy = spy(MyService.class);
doReturn(true).when(mySpy).validationETPer(any(Object.class), anyChar());
jobLauncherTestUtils.setMyService( mySpy ); // or something like that
// and NOW you can test
It's hard to go deeper in the details without knowing how the MyService is used in your actual code. Personally, I would suggest starting with unit tests without spring and using spring test only for higher level tests.

What is the purpose of Test Clean up

Can anyone please tell me in detail what is test clean up why we use it?
Why we use after initialize
What actually it does
Please tell me in detail
Test Cleanup is code that runs after each test.
Test cleanup is declared inside the same class where your tests are declared. Also any assertions you have that go in TestCleanup can fail the test. This is very useful if you have values you check for each test in the same location that could potentially fail the test.
[TestCleanup]
public void CleanUp()
{
AppManager.CheckForHandledExceptions();
}
Here are the important events to consider:
[ClassInitialize]
public static void Init(TestContext testContext)
{
//Runs before any test is run in the class - imo not that useful.
}
[TestInitialize]
public void Init()
{
//Runs just prior to running a test very useful.
}
Mostly I use TestInitialize to reset the uimap between tests, otherwise control references can go stale.
Next what runs at the end, once all the tests in your assembly have run (very good for checking for unhandled exceptions or maybe shutting down the application).
So if you run 100 tests via MTM, after the last one is finished, AssemblyCleaup will run, also note this method is a bit special it is declared once per assembly, in it's own class with the [CodedUITest] attribute on the class.
[CodedUITest]
public class TestRunCleanup
{
[AssemblyCleanup()]
public static void AssemblyCleanup()
{
AppManager.CloseApplicationUnderTest();
}
}

How do I mock a JSF FacesContext with a ViewMap for Unit Tests outside an actual web application?

EDIT: Cleaned up the question for readability. Please ignore comments up to October 31st.
In our application stack we work with many smaller jar modules that get combined into a final web application. One module defines JSF features, like implementing this ViewScope.
Now appart from integration testing we want to be able to unit test every part and thus need a way to mock a complete Faces Context (to be accessed via a wrapper) to test classes that use it.
The important part here is complete meaning it has to have an initialized ViewMap as this is where our ViewScope puts its objects.
I've tried different approaches:
1) shale-test: I've come the furthest with this but unfortunately the project is retired.
So far I've wrapped the FacesContext in a Provider which allows me to replace it with a Mocked FacesContext for testing. I've also modified the shale implementation of AbstractViewControllerTestCase to include an application context.
However when calling MockedFacesContext.getViewRoot().getViewMap() as this will throw an UnsupportedOperationException. The reasons seems to be that the MockApplication does not instantiate Application.defaultApplication (it's null) which is required for this method call. This seems to be a shale-test limitation.
2) JMock or mockito These seem to me not to not really mock anything at all as most members will just remain null. Don't know if JMock or mockito can actually call the propper initialization methods.
3) Custom Faces Mocker: To me this seems the only remaining option but we don't really have the time to analyse how Faces is initialized and recreate the behaviour for mocking purposes. Maybe someone has dont this before and can share major waypoints and gotchas?
Or is there any alternative way to mock a FacesContext outside a web application?
I would go with PowerMock+Mockito:
From your link:
private Map<String,Object> getViewMap() {
return FacesContext.getCurrentInstance().getViewRoot().getViewMap();
}
In the test:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ FacesContext.class });
public class TheTest {
/*
* fake viewMap.
*/
private Map<String,Object> viewMap = Maps.newHashMap() // guava
/**
* mock for FaceContext
*/
#Mock
private FacesContext faceContext;
/**
* mock for UIViewRoot
*/
#Mock
private UIViewRoot uiViewRoot;
#Before
public void setUp() {
Mockito.doReturn(this.uiViewRoot).when(this.faceContext).getViewRoot();
Mockito.doReturn(this.viewMap).when(this.uiViewRoot).getViewMap();
PowerMock.mockStatic(FacesContext.class);
PowerMock.doReturn(this.faceContext).when(FacesContext.class, "getCurrentInstance");
}
#Test
public void someTest() {
/*
* do your thing and when
* FacesContext.getCurrentInstance().getViewRoot().getViewMap();
* is called, this.viewMap is returned.
*/
}
}
Some reading:
http://code.google.com/p/powermock/wiki/MockitoUsage

Resources