How to get repetition count in a junit 5 extension - java

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;
}
}

Related

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

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.

How to correctly produce errors from a javac plugin

I'm trying to create a javac plugin which will do some simple source validation for test classes. Essentially I want to ensure that this piece of code is invalid:
#RunWith(Parameterized.class)
class Test {
}
i.e. The RunWith annotation must not contain a Parameterized value. I'm able to get to the point of detecting this but I'm unsure how to produce an error correctly; I want the compile to fail with an error. Of course I can throw an exception, but that doesn't seem right.
I'm following the excellent examples from http://www.baeldung.com/java-build-compiler-plugin. My code currently looks like this:
public class EnsureCorrectRunsWithPlugin implements Plugin {
public static final String NAME = "MyPlugin";
private Context context;
public String getName() {
return NAME;
}
public void init(JavacTask task, String... args) {
context = ((BasicJavacTask) task).getContext();
log("Hello from " + getName());
task.addTaskListener(new TaskListener() {
public void started(TaskEvent e) {
// no-op
}
public void finished(TaskEvent e) {
if (e.getKind() != TaskEvent.Kind.PARSE) {
return;
}
e.getCompilationUnit().accept(new TreeScanner<Void, Void>() {
#Override
public Void visitAnnotation(AnnotationTree annotation, Void aVoid) {
if (annotation.getAnnotationType().toString().equals(RunWith.class.getSimpleName())) {
log("visiting annotation: " + annotation.getAnnotationType());
List<? extends ExpressionTree> args = annotation.getArguments();
for (ExpressionTree arg : args) {
log(" value: " + arg.toString());
if (arg.toString().equals(Parameterized.class.getSimpleName())) {
// Produce an error here...
}
}
}
return super.visitAnnotation(annotation, aVoid);
}
#Override
public Void visitClass(ClassTree node, Void aVoid) {
log("visiting class: " + node);
return super.visitClass(node, aVoid);
}
}, null);
}
});
}
private void log(String message) {
Log.instance(context).printRawLines(Log.WriterKind.NOTICE, message);
}
}
Thanks for any guidance.
You can use Trees.printMessage to output an error message. The first argument controls whether its a warning or an error, and Kind.Error will generate an error.
So assuming you stashed Trees into a variable trees, you can do something like:
this.trees.printMessage(Kind.Error, "Error from JavaC plugin", tree, compilationUnitTree)
The third variable, tree, indicates the error span.

How do I check if an instance of a class has access to a method in another class?

I'm working on a small project where I want to have a list of a class called "DevelopmentEmployee", but only one of them is allowed to manipulate certain methods in another class "Project". The way I have implemented it, the class Project has a field called projectLeader, which is of the type DevelopmentEmployee. When a DevelopmentEmployee attempts to access methods in the class Project, I want to check if the DevelopmentEmployee is equal to the specific instance of Project's projectLeader.
Something like
public class Project {
private DevelopmentEmployee projectLeader;
private List < Activity > activities = new ArrayList < Activity > ();
public Project(DevelopmentEmployee pL) {
this.projectLeader = pL;
}
public void addActivity(String activityName) {
if (projectLeader.equals(DevelopmentEmployee * ) {
activities.add(activity);
}
}
}
But I can't figure out a way to make the access requirement work. How can the instance of the class Project know who is trying to access it?
You should also pass the DevelopementEmployee in addActivity for checking it against the projectLeader.
public void addActivity(String activityName,DevelopmentEmployee employee) {
if (projectLeader.equals(employee) {
activities.add(activity);
}
}
Then you need to override equals method in DevelopmentEmployee class, for proper checking of equality, like the one as shown below :
public boolean equals(DevelopementEmployee e){
if(e!=null && this.employeeId==e.employeeId)
return true;
else
return false;
}
Several possibilities come to mind:
Provide the instance of the one accassing the project method to the method:
public void addActivity(String activityName, DevelpmentEmployee user) {
if (projectLeader.equals(user)) {`
Create some class that holds information about active user and use that inside the methods:
public class Project {
private UserRegistry userRegistry;
private List<Activity> activities = new ArrayList<Activity>();
public Project(UserRegistry userRegistry) {
this.userRegistry = userRegistry;
}
public void addActivity(String activityName) {
if (userRegistry.isActiveUserProjectLeader()) {
activities.add(activity);
}
}
}
public class UserRegistry {
private DevelpmentEmployee projectLeader;
private DevelpmentEmployee activeUser;
private List<DevelpmentEmployee> user;
public void addUser(DevelpmentEmployee user) { ... }
public void makeProjectLeader(DevelpmentEmployee newLeader) { ... }
public void makeActiveUser(DevelpmentEmployee newActiveUser) { ... }
public boolean isActiveUserProjectLeader() { ... }
}`

Java - HashCode - Equals

I have a problem with Unit Tests in Java.
I put here my code and my error. On internet I found this is a problem with hashcode. I need to recreate them but I don't know why and how.
My method :
public void setGroupModel(GroupModel groupModel) {
this.groupModel = groupModel;
this.groupModel.add(this);
}
cellControler file :
public class CellController {
public void click(CellModel cellModel, HexModel hexModel)
{
GroupModel groupModel = new GroupModel();
cellModel.setGroupModel(groupModel);
hexModel.getGridContentModel().getArrayListGroupModel().add(groupModel);
}
}
My UnitTest :
public class CellControllerTest {
protected CellController cellController;
#Before
public void setUp() throws Exception {
cellController = new CellController();
}
#After
public void tearDown() throws Exception{
}
#Test
public void testClick() throws Exception{
GroupModel groupModel = new GroupModel();
CellModel cellModel = new CellModel();
HexModel hexModel = new HexModel(); // hexModel has an attribute : gridContentModel
cellController.click(cellModel, hexModel);
assertEquals(groupModel, cellModel.getGroupModel());
}
}
My error
java.lang.AssertionError: expected:<model.GroupModel#6d5380c2> but was:<model.GroupModel#45ff54e6>
I think the problem is : this.groupModel = groupModel;
What I have to write and why? :)
To compare is easy, you need to override hashCode and equals or use a comparator, if you did not do that then the message you get is perfectly normal.
Here you set the groupModel AND modify the groupModel.
public void setGroupModel(GroupModel groupModel) {
this.groupModel = groupModel;
this.groupModel.add(this); // the modification
}
In your test you compare the groupModel you just created and the groupModel that you get from cellModel.getGroupModel(), but that one has been modified, so the two objects are different
assertEquals(groupModel, cellModel.getGroupModel());

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