Static and Non Static in TestNg - selenium

I have senario where I want to understand use access modifier Static and non static in TestNG. Here is actual code `
public class BaseClass {
public WebDriver driver =null;
public File f = null;
public FileInputStream fs = null;
public static Properties config = null;
private final String configPath="C:\\Users\\prakumak\\eclipse-workspace\\WebDriverTestNGDDFramwork\\src\\MangoHCM\\Config.properties";
#BeforeClass
public void setup() throws Exception {
f = new File(configPath);
try {
fs = new FileInputStream(f);
config = new Properties();
config.load(fs);
}catch(FileNotFoundException e) {
System.out.println(" File is not present");
}catch(IOException e) {
System.out.println("File not loaded");
}
if(config.getProperty("BrowserName").equalsIgnoreCase("Firefox")) {
driver = new FirefoxDriver();
}else if(config.getProperty("BrowserName").equalsIgnoreCase("Chrome")) {
driver = new ChromeDriver();
}else {
throw new Exception("BrowserName is either not mentione OR not correct");
}
}
Scenario 1: When I make Properties variable STATIC and setup() method as NON static, I am still able to call Properties variable in non-static setup() method directly. How could it possible to use static variable in non static method ?
scenario 2: When I make Setup() method as STATIC and Properties variable as non-static then I am getting error saying that "annot make a static reference to the non-static field ". This is OK for me.
Please help me to static how does static and non static work in TestNG? Is it same as normal concept of Java or something is different here? does adding annotation in any menthod in testNG makes it static?

The concept of static and non-static are the same in Java and TestNG.
Non-static always requires a context, referenced by this. Static does not require a context, but you can use the class name. Use of the class name is not required if your code is within that class (i.e. BaseClass.config). The same rule applies for methods (i.e. BaseClass.setup() in your code, unless setup is declared as static).
If you add a non-static setup() method annotated with #Before, you would have two methods, one that requires a context and one that does not. To make your code more readable, i suggest that you rename your static setup() method to setupClass().
Since your method is annotated with #BeforeClass, it has to be static. It is bound to the class and not to a context. This is implicitly required by #BeforeClass.
#BeforeClass requires a static method
#Before requires a non-static method
You can always access field and methods that do not require a context from methods that do require a context. Keep in mind that fields that have no context are shared by static and non-static methods and even between different non-static methods that have a different context.
Basic rule is to stick with the same modifier, either non-static or static, for fields and methods.

Related

How to programmatically register extensions in Junit5

Say, a test needs a parameter that is only known when the tests are about to run.
#ExtendWith(MyParameterExtension.class)
public class Test {
protected final MyParameter p;
public Test(MyParameter p) {}
#Test
public void test() { assertSuccess(TestedCode.doComplexThing(p)); }
}
Only before the tests are executed, the specific contents of MyParameter instance can be determined. So I can have a resolver extension that simple pastes that parameter value where needed:
class MyParameterExtension implements ParameterResolver {
private final MyParameter myParameter;
public MyParameterExtension(MyParameter p) {
myParameter = p;
}
#Override
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
return (parameterContext.getParameter().getType() == MyParameter.class);
}
#Override
public MyParameter resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
return myParameter;
}
}
I run the tests by starting Junit5 from my own code. That's when I can determine what the corresponding parameter values are. Let's say these parameters drive the behavior of the tests, and a user can specify (i.e., over a CLI) the values that a run should use.
How do I register the extension with the test run, as I'm about to commence it?
void launchSuite(List<DiscoverySelector> selectors, Object something) {
// The input to this are all the necessary selectors.
LauncherDiscoveryRequest ldr = LauncherDiscoveryRequestBuilder.request()
.selectors(selectors).build();
Launcher launcher = LauncherFactory.create();
TestPlan plan = launcher.discover(ldr);
MyParameter myParameter = new MyParameter(something);
MyParameterExtension ext = new MyParameterExtension(myParameter);
// $TODO: how do I register my extension with the test run
// before starting it?
launcher.execute(plan);
}
Auto-registering extensions doesn't help me (how would that process know the value of MyParameter)
Using #RegisterExtension in the test code doesn't help me (A static block in the test code won't know the proper input for constructing instances of MyParameter)
Looking at the mechanics of launching the test, I don't see anything that lets me register those extensions in advance.
I considered using a ThreadLocal field in an extension registered statically but AFAIU, this won't (reliably) work because JUnit may create its own threads at least in certain cases.
I considered sticking the value of MyParameter in the "extension context", but I don't see a way to grab a hold of that before the test execution starts either. The root context is created in JupiterEngineDescriptor that is, if nothing else, all internal API.
The obvious solution is to stick the parameter in a static field somewhere, but that would preclude me from running tests with different parameters in parallel, unless I resort to loading tests into isolated class loaders, which sounds too cumbersome for something that I believe should be simpler. After all, all of the contexts of a test run are otherwise fully isolated.
What I'm ultimately trying to do, at then, as to make something like this possible:
// ...
new Thread(()->launchSuite(selectors, "assume Earth gravity")).start();
new Thread(()->launchSuite(selectors, "assume Mars gravity")).start();
So what's are the reasonable ways to wire something this together?
Let's start with the one thing that does not work: Using the launcher API.
The launcher API is a platform feature, whereas extensions are Jupiter-related. That's why there is no mechanism to register an extension in the API.
What should work, though, is #RegisterExtension - although you claim it would not. As the documentation shows it is not restricted to static fields. Therefore, whatever you do here:
MyParameter myParameter = new MyParameter(something);
MyParameterExtension ext = new MyParameterExtension(myParameter);
could be done in a static method to instantiate an extension during runtime:
public class Test {
private static MyParameterExtension createExtension() {
MyParameter myParameter = new MyParameter(something);
return new MyParameterExtension(myParameter);
}
#RegisterExtension
private MyParameterExtension my = createExtension();
#Test
public void test(MyParameter p) {
assertSuccess(TestedCode.doComplexThing(p));
}
}
If that doesn't work in your case, some information is missing from your problem statement IMO.
Update
If your extension creation code requires parameters that can only be determined at launch time, you have the option of adding configuration parameters to the discovery request:
LauncherDiscoveryRequest ldr = LauncherDiscoveryRequestBuilder.request()
.configurationParameter("selectors", "assume Earth gravity")
.selectors(selectors).build();
This parameter can then be retrieved within the extension:
class MyParameterExtension implements ParameterResolver {
...
#Override
public MyParameter resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
var selectors = extensionContext.getConfigurationParameter("selectors").orElse("");
return new MyParameter(selectors);
}
}

Why does ByteBuddy tell me that there is an ambiguity in my interceptor methods when there is only one such method?

(Trying to keep this simple.)
I have a (partial) ByteBuddy recipe like this:
builder
.method(someMatcher())
.intercept(MethodDelegation.to(this.interceptor));
I have an "interceptor" class defined like this:
private static final class Interceptor {
private Interceptor() {
super();
}
#RuntimeType
private final Object doSomething(#This final Proxy<?> proxy,
#SuperCall final Callable<?> callable,
#Origin final String methodSignature) throws Exception {
final Object proxiedInstance = proxy.getProxiedInstance();
// TODO: logic
return callable.call(); // for now
}
}
(The interceptor method needs to be non-static for various reasons not important here.)
When I create an instance of this ByteBuddy-defined class and call a simple public void blork() method on it, I get:
Cannot resolve ambiguous delegation of public void com.foo.TestExplorations$Frob.blork() to net.bytebuddy.implementation.bind.MethodDelegationBinder$MethodBinding$Builder$Build#3d101b05 or net.bytebuddy.implementation.bind.MethodDelegationBinder$MethodBinding$Builder$Build#1a9efd25
How can there be ambiguity when there is only one interceptor? What have I done wrong?
Byte Buddy just adds a method call to the instrumented class which needs to be able to see the target class. If it is private, it is ignored and Byte Buddy searches further up the hierarchy where it finally consideres the methods of Object which are all equally unsuited but therefore an ambiguity exception is thrown instead of an exception that no method could be bound.

Kotlin object, an implementation vs instance

In Objects in Kotlin: Create safe singletons in one line of code (KAD 27) Antonio Leiva states:
In fact, an object is just a data type with a single implementation.
I would expect to see the term instance rather than implementation used here. Is there some nuance that I am missing?
Sure it does have a single instance after all, but I believe what they meant to say is that whatever you write in an object is final and you can not override it. Even if you make it open(for argument purpose), you can not make an anonymous object out of it since the anonymous class can't be used on a SingleTon instance.
So " data type with a single implementation" means, whatever you write is the final implementation. An instance is, after all, a result of some implementation.
For reference, I am adding a decompiled code of object declaration.
public final class Test {
#NotNull
private static final String testMember = "Test";
public static final Test INSTANCE;
#NotNull
public final String getTestMember() {
return testMember;
}
private Test() {
}
static {
Test var0 = new Test();
INSTANCE = var0;
testMember = "Test";
}
}

How to disable static initializer?

Assuming my system under test looks like this:
public class SysUnderTest {
public int foo() {
Trouble trouble1 = new Trouble();
Trouble trouble2 = new Trouble();
return trouble1.water(1) + trouble2.water(2);
}
}
The test will looks something like
public class DummyTest {
#Tested SysUnderTest sut;
#Mocked Trouble trouble;
#Test
public void testTrouble() {
new Expectations() {{
trouble.water(anyInt); returns(10, 20);
}};
assertThat("mocked result", sut.foo(), is(30));
new FullVerificationsInOrder() {{
Trouble t1 = new Trouble();
Trouble t2 = new Trouble();
t1.water(1);
t2.water(2);
}};
}
}
However, Trouble is actually a 3rd-party lib class that I have no control, which it does static initialization which will fail in testing env.
public class Trouble {
static {
troubleInitialize();
};
public int water(int i) {
return 0;
}
private static void troubleInitialize() {
throw new RuntimeException("Trouble");
}
}
I know I can use MockUp<Trouble> to get rid of the static initializer but I have no idea how to make use of it in case as I want to (in my realistic case) be able to distinguish the two new instances (created in SysUnderTest) and verify their invocations. I have tried different ways but all failed with some reasons
Adding a new MockUp<Trouble>(){#Mock void $clinit(){} }; in #Before/#BeforeClass, and keep #Mocked Trouble trouble;. It seems not working because the mockup action happens after the DummyTest class is loaded, which will load (unmodified) Trouble class which will throw exception during static initialization
Adding the new Mockup in a TestSuite and call the DummyTest in suite, similar problem as 1.
Simply put the behavior of returning 20, 30 in the fake class, and remove usage of Expectations/Verifications but I have no way to verify which instance is called with what parameter.
Is there a better way to solve my problem? Actually I would want to keep using Expectaitons/Verifications, all I want is some way to disable the static initializer during unit test.
Use stubOutClassInitialization to change the mocked class's static init to an empty method when using Mocked.
#Mocked(stubOutClassInitialization=true) Trouble trouble;

JMockit: #Mocke and MockUp combination in the same test

What I have to do:
I have to test my spring mvc with JMockit. I need to do two things:
Redefine MyService.doService method
Check how many times redefined MyService.doService method is called
What the problem:
To cope with the first item, I should use MockUp; to cope with the second item I should use #Mocked MyService. As I understand this two approaches are overriding each other.
My questions:
How to override MyService.doService method and simultaneously check how many times it was invoked?
Is it possible to avoid mixing a behaviour & state based testing approaches in my case?
My code:
#WebAppConfiguration
#ContextConfiguration(locations = "classpath:ctx/persistenceContextTest.xml")
#RunWith(SpringJUnit4ClassRunner.class)
public class MyControllerTest extends AbstractContextControllerTests {
private MockMvc mockMvc;
#Autowired
protected WebApplicationContext wac;
#Mocked()
private MyServiceImpl myServiceMock;
#BeforeClass
public static void beforeClass() {
new MockUp<MyServiceImpl>() {
#SuppressWarnings("unused")
#Mock
public List<Object> doService() {
return null;
}
};
}
#Before
public void setUp() throws Exception {
this.mockMvc = webAppContextSetup(this.wac).build();
}
#Test
public void sendRedirect() throws Exception {
mockMvc.perform(get("/doService.html"))
.andExpect(model().attribute("positions", null));
new Verifications() {
{
myServiceMock.doService();
times = 1;
}
};
}
}
I don't know what gave you the impression that you "should use" MockUp for something, while using #Mocked for something else in the same test.
In fact, you can use either one of these two APIs, since they are both very capable. Normally, though, only one or the other is used in a given test (or test class), not both.
To verify how many invocations occurred to a given mocked method, you can use the "invocations/minInvocations/maxInvocations" attributes of the #Mock annotation when using a MockUp; or the "times/minTimes/maxTimes" fields when using #Mocked. Choose whichever one best satisfies your needs and testing style. For example tests, check out the JMockit documentation.