Get currently executing #Test method in #Before in JUnit 4 - java

I want to get currently executing test method in #Before so that I can get the annotation applied on currently executing method.
public class TestCaseExample {
#Before
public void setUp() {
// get current method here.
}
#Test
#MyAnnotation("id")
public void someTest {
// code
}
}

try TestName rule
public class TestCaseExample {
#Rule
public TestName testName = new TestName();
#Before
public void setUp() {
Method m = TestCaseExample.class.getMethod(testName.getMethodName());
...
}
...

Evgeniy pointed to the TestName rule (which i'd never heard of - thanks, Evgeniy!). Rather than using it, i suggest taking it as a model for your own rule which will capture the annotation of interest:
public class TestAnnotation extends TestWatcher {
public MyAnnotation annotation;
#Override
protected void starting(Description d) {
annotation = d.getAnnotation(MyAnnotation.class);
}
}

Related

Why Powermockito invokes my mocked method?

I want to mock private method, which called from my test method, but instead of mocking, PowerMockito invoke toMockMethod, and I get NPE.
toMockMethod is in the same class.
#RunWith(PowerMockRunner.class)
public class PaymentServiceImplTest {
private IPaymentService paymentService;
#Before
public void init() {
paymentService = PowerMockito.spy(Whitebox.newInstance
(PaymentServiceImpl.class));
MockitoAnnotations.initMocks(this);
}
#Test
public void test() throws Exception {
...
PowerMockito.doReturn(mockedReturn)
.when(paymentService,
"toMockMethod",
arg1, arg2);
}
}
Is it normal situation? What a sense to mock method if it has been invoked?
To enable static or non-public mocking with PowerMock for a class, the class should be added to annotation #PrepareForTest. In your case, it should be:
#RunWith(PowerMockRunner.class)
#PrepareForTest(PaymentServiceImpl.class)
public class PaymentServiceImplTest {
private IPaymentService paymentService;
#Before
public void init() {
paymentService = PowerMockito.spy(Whitebox.newInstance
(PaymentServiceImpl.class));
MockitoAnnotations.initMocks(this);
}
#Test
public void test() throws Exception {
...
PowerMockito.doReturn(mockedReturn)
.when(paymentService,
"toMockMethod",
arg1, arg2);
}
}
I'm gonna leave a second answer for my future self here. There's an alternative problem here. If you're calling Static.method make sure "method" is actually defined in Static and not up the hierarchy.
In my case the code called Static.method, but Static extends from StaticParent, and "method" is actually defined in StaticParent.
#RunWith(PowerMockRunner.class)
#PrepareForTest(StaticParent.class)
public class YourTestClass {
#Before
public init() {
PowerMockito.mockStatic(StaticParent.class);
when(StaticParent.method("")).thenReturn(yourReturnValue);
}
}
public class ClassYoureTesting {
public someMethod() {
Static.method(""); // This returns yourReturnValue
}

NPE on spring autowires form TestExecutionListener

This might have been coded wrongly, but any idea how it should be done is appreciated.
I have this class TestClass which needs to inject many service class. Since I can't use #BeforeClass on #Autowired objects, I result on using AbstractTestExecutionListener. Everything was working as expected but when I'm on #Test blocks, all objects are evaluated null.
Any idea how to solve this?
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = { ProjectConfig.class })
#TestExecutionListeners({ TestClass.class })
public class TestClass extends AbstractTestExecutionListener {
#Autowired private FirstService firstService;
// ... other services
// objects needs to initialise on beforeTestClass and afterTestClass
private First first;
// ...
// objects needs to be initialised on beforeTestMethod and afterTestMethod
private Third third;
// ...
#Override public void beforeTestClass(TestContext testContext) throws Exception {
testContext.getApplicationContext().getAutowireCapableBeanFactory().autowireBean(this);
first = firstService.setUp();
}
#Override public void beforeTestMethod(TestContext testContext) throws Exception {
third = thirdService.setup();
}
#Test public void testOne() {
first = someLogicHelper.recompute(first);
// ...
}
// other tests
#Override public void afterTestMethod(TestContext testContext) throws Exception {
thirdService.tearDown(third);
}
#Override public void afterTestClass(TestContext testContext) throws Exception {
firstService.tearDown(first);
}
}
#Service
public class FirstService {
// logic
}
For starters, having your test class implement AbstractTestExecutionListener is not a good idea. A TestExecutionListener should be implemented in a stand-alone class. So you might want to rethink that approach.
In any case, your current configuration is broken: you disabled all default TestExecutionListener implementations.
To include the defaults, try the following configuration instead.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = ProjectConfig.class)
#TestExecutionListeners(listeners = TestClass.class, mergeMode = MERGE_WITH_DEFAULTS)
public class TestClass extends AbstractTestExecutionListener {
// ...
}
Regards,
Sam (author of the Spring TestContext Framework)

JUnit: #Rule's overridden apply method not executed under test

I created a JUnit rule to rollback a javax.persistence transaction when any exception occurs (otherwise all further tests will fail since the transaction is in an inconsistent condition). The problem is that my rule will never be executed when the test starts, strictly speaking: the apply method is never executed. it does not even work when I put the #Rule declaration into the concrete class and initialize the transactionRule within the test. Here is how it looks like:
THE RULE
public class TransactionRule implements TestRule
{
private EntityManager entityManager;
public TransactionRule(EntityManager entityManager)
{
this.entityManager = entityManager;
}
#Override
public Statement apply(Statement base, Description description)
{
return new TransactionStatement(base);
}
public class TransactionStatement extends Statement
{
private final Statement runningTest;
public TransactionStatement(Statement runningTest)
{
this.runningTest = runningTest;
}
#Override
public void evaluate() throws Throwable
{
try
{
runningTest.evaluate();
}
catch (Exception e)
{
if (entityManager.getTransaction().isActive())
{
entityManager.getTransaction().rollback();
}
}
}
}
}
THE ABSTRACT CLASS THAT USES THE RULE
public abstract class AbstractIntegrationTest
{
//more members vars
#Rule
public TransactionRule transactionRule;
#BeforeClass
public static void setUpBeforeClass()
{
loadProperties();
entityManagerFactory = Persistence.createEntityManagerFactory("MyCuisinePersistenceTestUnit", connectionProperties);
entityManager = entityManagerFactory.createEntityManager();
}
#Before
public void setUp()
{
transactionRule = new TransactionRule(entityManager);
entityManager.clear();
}
//more code
}
THE TEST CLASS WITH THE DEFECTIVE TEST
public class RecipePersistenceITest extends AbstractIntegrationTest
{
//more tests
#Test
public void persistenceOfRecipeWithUserCategorySuccessful()
{
//Test that fails
}
}
Any ideas?
Test rules are invoked before methods annotated with #Before, so trying to assign a rule in #Before will have no effect (although I would have expected it to throw an exception instead).
Instead assign the rule on definition (and make the field final), and do any additional config (if necessary) in your #Before.
Note that each test method is executed in a new instance of the test class, so defining a rule as a final field is no problem.

How should a custom Guice scope be integrated with TestNG?

We use a custom Guice scope, #TestScoped, for some of our JUnit tests that lasts for a single test method, and a JUnit #Rule to enter and exit the scope appropriately. It looks like this:
public class MyJUnitTest {
#Rule public CustomRule customRule = new CustomRule(MyModule.class);
#Inject private Thing thing;
#Test
public void test1() {
// Use "thing"
}
#Test
public void test2() {
// Assuming "Thing" is #TestScoped, we'll have a new instance
}
}
We're starting to use TestNG for some of our tests in other projects, and we'd like to have a similar pattern. So far we've come up with this:
#Listeners(CustomTestNGListener.class)
#Guice(modules = MyModule.class)
public class MyTestNGTest {
#Inject private Provider<Thing> thingProvider;
#Test
public void test1() {
Thing thing = thingProvider.get();
// Use "thing"
}
#Test
public void test2() {
Thing thing = thingProvider.get();
// Assuming "Thing" is #TestScoped, we'll have a new instance
}
}
public class CustomTestNGListener implements IHookable {
#Override
public void run(IHookCallBack callBack, ITestResult testResult) {
TestScope.INSTANCE.enter();
try {
callBack.runTestMethod(testResult);
} finally {
TestScope.INSTANCE.exit();
}
}
}
There are a couple issues with this design:
Unlike JUnit, TestNG uses the same instance of the test class for each method. That means we have to inject Provider<Thing> instead of just Thing, which is awkward.
For some reason, CustomTestNGListener is running on all of our tests, even ones that don't have that #Listeners(CustomTestNGListener.class) annotation. I've worked around this by explicitly checking for that annotation in the listener itself, but it feels like a hack (though I do see that MockitoTestNGListener does the same thing).
Does someone with more familiarity with TestNG have any suggestions for dealing with these issues?
Instead of
public class MyTestNGTest {
#Inject private Provider<Thing> thingProvider;
#Test
public void test1() {
Thing thing = thingProvider.get();
In TestNG you can used
public class MyTestNGTest {
#Inject
private Thing thingInjected;
private Thing thing;
#BeforeTest
public void doBeforeTest() {
thing = thingInjected.clone();
}
Or just call thingProvider.get() in doBeforeTest(), it's better in you have a lot of # Test
public class MyTestNGTest {
#Inject private Provider<Thing> thingProvider;
private Thing thing;
#BeforeTest
public void doBeforeTest() {
thing = thingProvider.get();
}

Mocking a method in an element of a list

I have this code in my Subject Under Test:
public class Widget {
private Set<Thing> things;
public Set<Thing> getThings() { return things; }
public void setThings(Set<Thing> things) { this.things = things; }
public void performAction(PerformingVisitor performer) {
for (Thing thing: getThings())
{
thing.perform(performer);
}
}
}
My JUnit/Mockito test looks like:
#RunWith(MockitoJUnitRunner.class)
public class WidgetTest {
#Mock private PerformingVisitor performer;
#Mock private Thing thing;
#InjectMocks private Widget widget;
#Before
public void setUp() throws Exception {
Set<Thing> things = new HashSet<Thing>();
things.add(thing);
widget.setThings(things);
MockitoAnnotations.initMocks(this);
}
#Test
public void shouldPerformThing() {
Mockito.when(thing.perform(Mockito.any(PerformingVisitor.class))).thenReturn(true);
widget.performAction(performer);
Mockito.verify(thing).perform(Mockito.any(PerformingVisitor.class));
}
}
However, this gives me the error:
Wanted but not invoked:
thing.perform(<any>);
-> at com.myclass.ThingTest.shouldPerformThing(WidgetTest.java:132)
I've verified that the code enters the for loop and should be calling the actual thing.perform(performer); line, but my mock does not seem to be recording a call.
I think you need initMocks before the mock injection.
Could you try to change your setUp method for this:
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
Set<Thing> things = new HashSet<Thing>();
things.add(thing);
widget.setThings(things);
}
Hope it works
From the MockitoJUnitRunner javadoc:
Initializes mocks annotated with Mock, so that explicit usage of MockitoAnnotations.initMocks(Object) is not necessary.
So, if you remove
MockitoAnnotations.initMocks(this)
from your setUp method, the test pass.

Categories

Resources