Passing output of one test method to another method testng - java

I have to write the following unit test cases in testng:
saveProductTest which would return productId if product details are saved successfully in DB.
modifyProductTest, it should use previously saved productId as a parameter.
I am taking the product details input(PrdouctName, ReleaseDate) for saveProductTest and modifyProductTest method from an XML file using testNg data providers.Since productId is generated in save method, I have to pass it to the modify method.
What is the best way to pass output of one test method to another method in testng.

With all due respect to simendsjo, the fact that all tests should be independent from each other is a dogmatic approach that has a lot of exceptions.
Back to the original question: 1) use dependent methods and 2) store the intermediate result in a field (TestNG doesn't recreate your instances from scratch, so that field will retain its value).
For example
private int mResult;
#Test
public void f1() {
mResult = ...
}
#Test(dependsOnMethods = "f1")
public void f2() {
// use mResult
}

With the ITestContext object. It's a object available globally at the Suite context and disponible via parameter in each #Test.
For example:
#Test
public void test1(ITestContext context, Method method) throws Exception {
// ...
context.setAttribute(Constantes.LISTA_PEDIDOS, listPaisPedidos);
// ...
}
#Test
public void test2(ITestContext context, Method method) throws Exception {
List<PaisPedido> listPaisPedido = (List<PaisPedido>)
context.getAttribute(Constantes.LISTA_PEDIDOS);
// ...
}

Each unit test should be independent of other tests so you more easily can see what fails. You can have a helper method saving the product and returning the id and call this from both tests.

Related

How to test update function in Rest API?

I can't find a way to test my update method using JUnit. I am mocking the necessary repo and services. But when I call findById(Mockito.any()) it can't find anything so it throws an exception.
Here is my test class:
#ExtendWith(MockitoExtension.class)
class ApplicantServiceTest {
#Mock
private ApplicantRepository applicantRepository;
#Mock
private CreditRatingService creditRatingService;
#Mock
private ApplicantMapper applicantMapper;
#InjectMocks
private ApplicantService applicantService;
#Test
void update() {
Applicant applicant = getSampleApplicants().get(1);
Applicant updatedApplicant = new Applicant(1L,2141245L,"ege","c0skun",2523,"21412412",null,null);
Mockito.when(applicantService.update(applicantMapper.toDTO(applicant),Mockito.any())).thenReturn(applicant);
Assert.assertEquals(applicant.getIdentificationNumber(),updatedApplicant.getIdentificationNumber());
Assert.assertEquals(applicant.getPhoneNumber(), updatedApplicant.getPhoneNumber());
Assert.assertEquals(applicant.getFirstName(), updatedApplicant.getFirstName());
assertEquals(applicant.getMonthlyIncome(), updatedApplicant.getMonthlyIncome());
Assert.assertEquals(applicant.getId(), updatedApplicant.getId());
}
And this is the method I am trying to test:
public Applicant update(ApplicantDTO applicantDTO,Long id) {
Applicant byId = getById(id);
if (applicantDTO.getMonthlyIncome()!=byId.getMonthlyIncome()){
byId.setMonthlyIncome(applicantDTO.getMonthlyIncome());
}
if (!Objects.equals(applicantDTO.getFirstName(), byId.getFirstName())){
byId.setFirstName(applicantDTO.getFirstName());
}
if (!Objects.equals(applicantDTO.getLastName(), byId.getLastName())){
byId.setLastName(applicantDTO.getLastName());
}
if (!Objects.equals(applicantDTO.getPhoneNumber(), byId.getPhoneNumber())){
byId.setPhoneNumber(applicantDTO.getPhoneNumber());
}
if (!Objects.equals(applicantDTO.getIdentificationNumber(), byId.getIdentificationNumber())){
byId.setIdentificationNumber(applicantDTO.getIdentificationNumber());
}
return applicantRepository.save(byId);
}
This is the output:
17:43:19.520 [main] ERROR com.egecoskun.finalproject.services.ApplicantService - Applicant not found by id : null
Related Applicant not found with : [id : null]
EntityNotFoundException(details=Some Special Details)
at com.egecoskun.finalproject.services.ApplicantService.lambda$getById$0(ApplicantService.java:47)
at java.base/java.util.Optional.orElseThrow(Optional.java:403)
at com.egecoskun.finalproject.services.ApplicantService.getById(ApplicantService.java:45)
at com.egecoskun.finalproject.services.ApplicantService.update(ApplicantService.java:75)
at com.egecoskun.finalproject.services.ApplicantServiceTest.update(ApplicantServiceTest.java:136)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...
Can someone explain how to unit test my update method?
The problem with your test code is that you've mixed mocking a method for a mock object (e.g. applicantRepository) with calling the tested method on an object under test (applicantService). We use when(...) to define the mocked behavior in Mockito and after that the actually tested code should be called (without the when()).
What you probably want to do is: mock retrieving the applicant object by ID, mock saving the modified object, run the update method to test it and assert the result.
To mock the behavior of the applicantRepository you need to tell Mockito what is the expected outcome of its methods calls, for example (I made a few assumptions for the code that is not attached):
when(applicantRepository.findById(anyLong())).thenReturn(applicantFromDb);
when(applicantRepository.save(notNull())).thenAnswer(returnsFirstArg());
(applicantFromDb is an object created in the test method)
After that when you call your update method, the mocked behavior above will be used:
Applicant result = applicantService.update(...);
Now you can assert the result returned from the tested method.
ApplicationService is your class under test. The exception you're getting is coming from ApplicationService.getById() method called at the start of update() method you're testing. You did not show us that method, but at a guess it calls the repository to get an instance by id. Your Repository mock is not set up to return anything when asked for any entity, so it returns null. Which seems to trigger the orElseThrow clause in the getById() method.
As such what you're seeing is likely the expected behaviour - when trying to update with an id that does not exist in the repository (repository returns null) service throws an exception. If you want to test the case where the entity is present you need to mock the repository appropriately.

Running only the tests with #MyTest inside java application

I have a TestRunner class:
public class TestRunner {
private String result = "";
public void runTests(List<String> testClassNames) {
for (String testClassName : testClassNames) {
}
}
public String getResult() {
return result;
}
}
Then I have two test classes and I should run only the tests with #MyTest from both classes. getResult() should essentialy return "exampleTest() - OK" or "exampleTest() - FAILED", depending on if the test passes. Test class looks like this:
public class ExampleTests1 {
#MyTest (expected = IllegalStateException.class)
public void test1() {
throw new IllegalStateException();
}
#MyTest (expected = IllegalStateException.class)
public void test2() {
throw new RuntimeException();
}
}
I tried to do it with JUnitCore and Result, but couldn't find a way to get the test method name to add to the result. Is there another way?
You'll have to use reflection in this case.
This is kind of how JUnit works internally:
Since this sounds as a homework/assigment for educational purposes (If you're developing a "real" application - then just use JUnit or TestNG and don't write anything like this by yourself :) ), I won't provide a full solution however this is what you should do:
For each class identified by a className you should get a java.lang.Class that describes this class name. You can use Class.forName(...)
Then you should get all the methods of that class (by reflection) and for each method run the following:
2.1 Check whether the method is marked with an annotation #MyTest. If it doesn't - don't handle it
2.2 Also check whether the method name starts with test (String has startsWith method)
2.3 If you found out that the test class contains test methods, then:
2.3.1 Create an instance of the Test Class (probably you can assume that it has no-ops constructor, then use newInstance())
2.3.2 Run the method (again by reflection). Check the result / surround the execution call with try/catch block to intercept errors.
2.3.3 Print the Result as specified in the assignment :)

Mockito.donothing() also check inside the method?

So,I want to call the donothing() method while writing the unit test for my perticular method, what I understand of using donothing is that "it tells Mockito to do nothing when a method in a mock object is called".
But in my case when I want to tells mockito to do nothing while calling the void method, it also checks the information that written inside the method too.
Why this is happen, Is donothing method also checks inside the method or it just simply skip the testing for it.?
E.g
this is the method in that I want to call donothing:
public void deleteTemporaryRemoteBranch(final File gitFile, final String branchName) throws IOException,
GitAPIException {
final Git openedRepo = Git.open(gitFile);
//delete branch 'branchName' locally
openedRepo.branchDelete().setBranchNames(branchName).setForce(true).call();
//delete branch 'branchName' on remote 'origin'
RefSpec refSpec = new RefSpec()
.setSource(null)
.setDestination(String.format(BRANCH_HEAD_REF, branchName));
openedRepo.push().setRefSpecs(refSpec).setRemote(LambdaEnv.ORIGIN).call();
}
This is the test method :
private static final String REPO_LOCATION = "/tmp/JGitClientTest12-repo/";
private static final File REPO_FILE = new File(REPO_LOCATION);
#Test
public void clone23_happyCase2() throws Exception {
Mockito.doNothing().when(jgitAccessor).deleteTemporaryRemoteBranch(Mockito.any(),Mockito.anyString());
classUnit.deleteTemporaryRemoteBranch(REPO_FILE,Mockito.anyString());
}
When I run this method it show me the error,
java.lang.IllegalArgumentException: Invalid refspec refs/heads/
at org.eclipse.jgit.transport.RefSpec.checkValid(RefSpec.java:539)
at org.eclipse.jgit.transport.RefSpec.setDestination(RefSpec.java:337)
So why this is testing inside the deleteTemporaryRemoteBranch method, even I call donothing() in it.?
I am new to unit testing.Any suggestion!!
Also any suggestion for this issue:
java.lang.IllegalArgumentException: Invalid refspec refs/heads/
at org.eclipse.jgit.transport.RefSpec.checkValid(RefSpec.java:539)
at org.eclipse.jgit.transport.RefSpec.setDestination(RefSpec.java:337)
As you mentioned, doNothing does nothing, but in the example that you have put you are not using the mocked class, you are calling another class.
You should change
classUnit.deleteTemporaryRemoteBranch(REPO_FILE,Mockito.anyString());
for
jgitAccessor.deleteTemporaryRemoteBranch(REPO_FILE,Mockito.anyString());
In other way, that test does not make much sense since by default the mocked methods do not do
https://www.javadoc.io/doc/org.mockito/mockito-core/2.8.9/org/mockito/Mockito.html#doNothing()

Unit Testing Java Code - Mocking a non-static method of a different class

public class First {
public First(){
}
public String doSecond(){
Second second = new Second();
return second.doJob();
}
}
class Second {
public String doJob(){
return "Do Something";
}
}
Here I want to test the method "doSecond()" of class "First". For the same, I want to mock the method "doJob" of class "Second".
I know that I can create a mocked instance of class "Second" using the code below.
Second sec = mock(Second.class);
when(sec.doJob()).thenReturn("Stubbed Second");
But I cannot relate this mocked instance with class "First" as of the current code.
Without refactoring the source code, is there any way by which i can achieve the requirement.
Please help.
Take a look at powermock's ability to intercept calls to new and return mocks instead
https://code.google.com/p/powermock/wiki/MockConstructor
This doesn't require changing any sourcecode.
here's the test code where we actually return a mock when First.doSecond() calls new Second()
#RunWith(PowerMockRunner.class)
#PrepareForTest(First.class)
public class TestFirst {
#Test
public void mockSecond() throws Exception{
Second mock = PowerMockito.mock(Second.class);
PowerMockito.whenNew(Second.class).withNoArguments().thenReturn(mock);
PowerMockito.when(mock.doSecond()).thenReturn("from mock");
First first = new First();
assertEquals("from mock", first.doSecond());
}
}
It's tricky to mock an instance that you create inside of a method, but it's possible.
Using PowerMock, you can accomplish this with the PowerMock.expectNew() method:
#RunWith(PowerMockRunner.class)
#PrepareForTest(First.class)
public class StackOverflowTest {
#Test
public void testFirst() throws Exception {
Second secondMock = EasyMock.createMock(Second.class);
PowerMock.expectNew(Second.class).andReturn(secondMock);
expect(secondMock.doSecond()).andReturn("Mocked!!!");
PowerMock.replay(secondMock, Second.class);
String actual = new First().doSecond();
PowerMock.verify(secondMock, Second.class);
assertThat(actual, equalTo("Mocked!!!"));
}
}
Effectively, PowerMock is proxying the creation of the new object and substituting whatever value we want when we invoke doSecond().
So, it's possible. However, this is a terrible practice to get into.
One typically wants to mock objects if they involve an outside concern, such as another layer (i.e. database, validation), or if the desired output is coming from other objects that are injected but are safe enough to consider tested.
If your method is capable of getting or retrieving data from a non-injectable source, you should not want to mock that out.
Considering that your method is simple and straightforward, you should really not need to do any mocks here at all. But if you felt that you were forced to, you could do one of a few things:
Create a factory for the creation of Second, and mock the results of the returning factory object with Mockito.
Pass in an instance of Second to that method, and use Mockito as the mock instance.
Declare it as a field (i.e. injected dependency), and use Mockito.
For completeness, here is how the test can be written with the JMockit mocking API, without any refactoring of the original code under test:
public class ExampleTest
{
#Test
public void firstShouldCallSecond(#Mocked final Second secondMock) {
new NonStrictExpectations() {{
secondMock.doJob(); result = "Mocked!!!";
}};
String actual = new First().doSecond();
assertEquals("Mocked!!!", actual);
}
}

How do I share state between JUnit tests?

I have a test class extending junit.framework.TestCase with several test methods.Each method opens a HTTP connection to server and exchange request and response json strings.One method gets a response with a string called UID(similar to sessionId) which i need to use in subsequent requests to the server.
I was previously writing that string to a file and my next requests read that file for string.I am running one method at a time.Now I am trying to use that string without file operations.I maintained a hastable(because there are many UIDs to keep track of) in my test class as instance variable for the purpose , but eventually found that class is getting loaded for my each method invocation as my static block is executing everytime.This is causing the loss of those UIDs.
How do I achieve this without writing to file and reading from it?
I doubt whether my heading matches my requirement.Someone please edit it accordingly.
You will need a static variable for this because each test gets its own instance of the test class.
Use this pattern:
private static String uuid;
private void login() {
// Run this only once
if (null != uuid) return;
... talk to your server ...
uuid = responseFromServer.getUuid();
}
#Test
public void testLogin() {
login();
assertNotNull( uuid );
}
#Test
public void someOtherTest() {
login();
... test something else which needs uuid ...
}
#Test
public void testWithoutLogin() {
... usual test code ...
}
This approach makes sure that login() is called for each test that needs it, that it's tested on its own and that you can run each test independently.
JUnit will create a new instance of the class for each test. Consequently you should likely set up and store this info as static to the class, using a #BeforeClass annotated static method.
See this SO answer for more info.

Categories

Resources