How to mock the value of a parameter in a service class - java

How can I test the following service method with Junit test? It's a very simple rebuild of my code and only an example.
I want to test in a JUnit test, what's happening, if the file string is empty or null.
Unfortunately I'm new to testing with JUnit. I read already some examples for rest controller and services and repos to me mocked and the methods for it, but here I have no idea how it could work. May someone can help?
public class MyService {
private String fileName = "src/main/resources";
// or
// private String fileName = ${modulename.config.filename};
// #Autowired
// private RepoService RepoService;
#EventListener
public void init(ContextRefreshedEvent event) {
try {
myMethod();
} catch (Exception e) {
// LOGGING
};
}
public void myMethod() {
if(fileName != null && !fileName.isEmpty()) {
// doSomething with file and IOException
// save in repo
} else {
// LOGGING
}
}
}
public void myMethod() {
if(fileName != null && !fileName.isEmpty()) {
// doSomething with IOException
} else {
// LOGGING
}
}
}
The test should look like the following. I tried to set the value somehow in the test, but it does not make sense and it's not set then.
#SpringBootTest
class DemoApplicationTests {
#Test
public void fileNameTest() {
// GIVEN
//Mockito.when()
// WHEN
// THEN
}
}

To change the value of a private variable Use Field modification using Reflection API.
Here's a nice explanation on how to do this.

Related

Mockito -- Response from service returns null in test - Java

I'm working on testing a class. This class calls on a service (let's say its called client, and we want to call client.put())
put() should return a response, but at least in the test, the response is null
I don't know if I just didn't setup the mock correctly and wanted to sanity check with you guys here
public class ATest {
#Mock
private ServiceProto.PutItemsResponse res;
...(private variables)...
#Before
public void setUp() throws Exception {
client = mock(Client.class);
clientFactory = mock(ClientFactory.class);
when(clientFactory.get(any())).thenReturn(client);
...(initializing private vars for constructor as mock variables, example below...)
captionConverter = mock(CaptionToCTItemConverter.class);
when(privateVar.convert(any(obj.class))).thenReturn(Item.newBuilder().build());
classAToTest = spy(new ClassAToTest(private variables);
}
#Test
public void putItem() {
long id = 4710582L;
AObject aObject = testUtils.getObject();
doReturn(res).when(client).putItems(any(ServiceProto.PutItemsRequest.class));
System.out.println("result is "+ res);
try {
classAToTest.putMethod(aObject);
}
catch (NullPointerException e) {
}
verify(creativeToolsClient, Mockito.times(1)).putItems(any(IngestionServiceProto.PutItemsRequest.class));
}
}
And this is the method being tested
public void putMethod(AObject aObject) {
final String id = Long.toString(aObject.getId());
ServiceProto.PutItemsResponse putItemsResponse = null;
Exception putItemsFailure = null;
putItemsResponse =
client.putItems(ServiceProto.PutItemsRequest.newBuilder()
.putItems(
id,
ServiceProto.PutItemsRequest.Item.newBuilder()).build())
.build());
if (putItemsResponse == null) {
logger.warning("PutItems request has failed: "+
(putItemsFailure == null ? "null" : putItemsFailure.getMessage()));
}
}
and when I run it it gives the warning
The putItems method works for other people. Did I set up mock incorrectly?
res variable is not initialized. To mock objects with #Mock annotation use
#ExtendWith(MockitoExtension.class)
public class ATest {
...

How to get repetition count in a junit 5 extension

I try to write my own JUnit 5 extension, providing some simple information about test duration.
I also want to print out the repetition information but how can I access these informations in the extension?
Are there any simple ways instead of reflection or writing and parsing the numbers to the display name?
simple example:
#ExtendWith(TimingExtension.class)
public class MyTestClass {
#RepeatedTest(value = 5, name = "{currentRepetition}/{totalRepetitions}")
public void myTest(TestInfo testInfo, RepetitionInfo repInfo) {
// do some work here...
}
}
public class TimingExtension implements AfterTestExecutionCallback {
#Override
public void afterTestExecution(ExtensionContext context) throws Exception {
if(context.getRequiredTestMethod().getDeclaredAnnotation(RepeatedTest.class) != null) {
System.out.println("This was test X of Y"); // how to get currentRepetition and totalRepetitions here?
}
}
}
Unfortunately there is no support for parameter injection in extensions. It's only one way. So in order to get RepetitionInfo in your TimingExtension you have to set it.
First you need to use #RegisterExtension e.g.
public class MyTestClass {
#RegisterExtension
TimingExtension timingExt = new TimingExtension();
#RepeatedTest(value = 5, name = "{currentRepetition}/{totalRepetitions}")
public void myTest(TestInfo testInfo, RepetitionInfo repInfo) {
timingExt.setRepetitionInfo(repInfo);
// do some work here...
}
}
public class TimingExtension implements AfterTestExecutionCallback {
private RepetitionInfo repInfo;
#Override
public void afterTestExecution(ExtensionContext context) throws Exception {
if (context.getRequiredTestMethod().getDeclaredAnnotation(RepeatedTest.class) != null && repInfo != null) {
System.out.println(String.format("This was test %d of %d", repInfo.getCurrentRepetition(), repInfo.getTotalRepetitions()))
repInfo = null;
}
}
public void setRepetitionInfo(RepetitionInfo repInfo) {
this.repInfo = repInfo;
}
}

Junit Test Bool Value

Hello Every One I Have This Method Which it Checks if the Input String Is Numbers only And Its Return True Or False
I Want To Make A Junit Test For this method and Actually I Don't know how to test Method Like This Can Any One Help And Thank You All.
My Method:
private Boolean Check_Ean(String EAN_Ch)
{
Long EAN;
try
{
EAN = Long.parseLong(EAN_Ch);
return true;
}
catch (NumberFormatException e)
{
return false;
}
}
First you need to create a class in the test folder(located at the same path as main). Then you need to use their annotations to or either Prepare the information, Test and Destroy the information(usefull when you have DB connection opens or streams):
public class TestClass {
#Before
public void setup() {
//prepare information
}
#Test
public void testCheck_Ean() {
boolean result = Check_Ean(...);
Assert.assertTrue(result);
}
#After
public void destroy() {
//if you need to "destroy" some info
}
}
tester = new CLASS_NAME();
assertTrue(tester.Check_Ean("5");
assertFalse(tester.Check_Ean("this is noot a Long");
You might be overthinking it. Also the Check_Ean method maybe could be static if you pass the Ean as a parameter rather than getting a class variable.

ITest .getTestName() returns null if test is skipped (because of dependsOnGroups)

What I want to do
I'm trying to generate a custom test report, which displays a custom test name. I do this by implementing "the ITest strategy" where you override the getTestName() method to provide your own.
In my report, I have the method name (from .getMethodName(), for example testIfStatusCodeIs200) and the test name (from .getTestName(), which I customise, and returns for example Tested endpoint is: http://cakeAPI/api/cakes/cakeId).
How the code looks like
public class BaseTest implements ITest {
private String uri = null;
public BaseTest(String uri) {
this.uri = uri;
}
#Test (groups = { "myGroup" })
public void test1() {
// do something
}
#Test (dependsOnGroups = { "myGroup"})
public void test2() {
// do something
}
public String getTestName() {
return uri;
}
}
This is the report generator logic. This is a pretty big function and most of it consists in appending and writing to an HTML file, so I voluntarily cut out pieces that I believe are non important for the problem:
public class CustomTestNGReporter implements IReporter {
public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory) {
try {
// Create test methods summary data.
String customTestMethodSummary = this.getTestMehodSummary(suites);
//... Append results to html
} catch (Exception ex) {
ex.printStackTrace();
}
}
/* Get test method summary info. */
private String getTestMehodSummary(List<ISuite> suites) {
try {
for (ISuite tempSuite : suites) {
Map<String, ISuiteResult> testResults = tempSuite.getResults();
for (ISuiteResult result : testResults.values()) {
ITestContext testObj = result.getTestContext();
/* Get failed test method related data. */
IResultMap testFailedResult = testObj.getFailedTests();
String failedTestMethodInfo = this.getTestMethodReport(testFailedResult);
/* Get skipped test method related data. */
IResultMap testSkippedResult = testObj.getSkippedTests();
String skippedTestMethodInfo = this.getTestMethodReport(testSkippedResult);
/* Get passed test method related data. */
IResultMap testPassedResult = testObj.getPassedTests();
String passedTestMethodInfo = this.getTestMethodReport(testPassedResult);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
/* Get failed, passed or skipped test methods report. */
private String getTestMethodReport(IResultMap testResultMap) {
Set<ITestResult> testResultSet = testResultMap.getAllResults();
for (ITestResult testResult : testResultSet) {
String testURI = testResult.getTestName();
System.out.println(testURI); // null for skipped tests
}
return null;
}
What is the problem
The problem is that if test1() fails, then test2() is skipped, and it seems that in this case getTestName() for test2 returns null.
For example, if the test of testIfStatusCodeIs200 fails, then I will skip testIfResponseHas10Elements. The test name associated with testIfStatusCodeIs200 will return the custom test name, while the test name of testIfResponseHas10Elements will return null.
Is there a way to 'force' getTestName() to be evaluated even though the test has been skipped ?
If you make use of the latest released version of TestNG (6.14.3) you will not see any null values. You will instead at-least get the actual #Test annotated method name.
I have filed a bug for ensuring that if there's an ITest implementation available in the test class, then TestNG should always retrieve that even for skipped methods as well.
You can track the issue here: https://github.com/cbeust/testng/issues/1756
The fix should be available in the upcoming version of TestNG viz., 7.0.0
You can add yourself as a watcher to the above mentioned issue to track it.

How to create own annotation for junit that will skip test if concrete exception was thrown during execution?

My application have several execution modes, and in 1 mode it is normal that some of my tests will throw a concrete exception. I need to annotate this methods with something like #SkipOnFail that will set method as skipped if exception was thrown.
thanks in advance!
#Edit(for my question to be more clear)
#Test(expected=ConcreteException.class)
does not work for me because i need my tests to pass even if ConcreteException.class was not thrown(expected tag in junit will mark my test as failed if this exception won't be thrown), and to be skipped otherwise. In all other cases it should work as always.
#Solution that worked for me(junit v4.7) thx to #axtavt
#Rule
public MethodRule skipRule = new MethodRule() {
public Statement apply(final Statement base, FrameworkMethod method, Object target) {
if(method.getAnnotation(SkipOnFail.class) == null) return base;
return new Statement() {
#Override
public void evaluate() throws Throwable {
try{
base.evaluate();
} catch (ConcreteException e) {
Assume.assumeTrue(false);
}
}
};
}
};
#Thx
I don't think that such a feature is available out of the box, but it should be pretty easy to implement with custom TestRule and Assume, something like this:
#Rule
public TestRule skipRule = new TestRule() {
public Statement apply(final Statement base, Description desc) {
if (desc.getAnnotation(SkipOnFail.class) == null) return base;
return new Statement() {
public void evaluate() throws Throwable {
try {
base.evaluate();
} catch (MyExceptoion ex) {
Assume.assumeTrue(false);
}
}
};
}
};
What about using JUnit Extensions?
The following example is taken from their Tutorial.
It provides aditional annotations for Prerequisites (#Prerequisite): Ignore tests based on conditions.
The required approach would be to check this during running tests. So you can simply add a #Prerequisite(requires="") annotation.
public class TestFillDatabase {
#Prerequisite(requires = "databaseIsAvailable")
#Test public void fillData() {
// ...
}
public boolean databaseIsAvailable() {
boolean isAvailable = ...;
return isAvailable;
}
}
public class TestFillDatabase {
#Prerequisite(requires = "databaseIsAvailable")
#Test public void fillData() {
// ...
}
public boolean databaseIsAvailable() {
boolean isAvailable = ...;
return isAvailable ;
}
}
This specified methods with #Prerequisite(requires = "databaseIsAvailable") must be a public method, returning a boolean or Boolean value.
If these methods will be consolidated in helper classes, you can also specify static methods within a class to be called using #Prerequisite(requires = "databaseIsAvailable", callee="DBHelper").
public class TestFillDatabase {
#Prerequisite(requires = "databaseIsAvailable", callee="DBHelper")
#Test public void fillData() {
// ...
}
}
public class DBHelper {
public static boolean databaseIsAvailable() {
boolean isAvailable = ...;
return isAvailable ;
}
}
Also using the Assume class (since jUnit 4.4), you can use assumeNoException():
try{
base.evaluate();
} catch (ConcreteException e) {
Assume.assumeNoException("Concrete exception: skipping test", e);
}
I searched for the docs about JUnit and it appears that from version 4.9 they have introduced what they call test rules (see TestRule). You may start from this.
The ExpectedException class marked as #Rule could be of some help in order to check for exceptions thrown but not mandatory for the test to pass.
For more advanced usage I cannot say for the moment as I've just discovered it.

Categories

Resources