I want to extend BaseClass from all test cases class.
For some test cases I want to login with Admin credentials and for some with Customer.
Previously this code was working properly as launchBrowserAndLogin() method was not having any parameters.
Is there any way for extending class with parameter?
Here is my code:
public class BaseClass {
public BaseClass() {
}
#BeforeMethod
public void launchBrowserAndLogin(String userType) {
if(userType.equals("Admin")) {
launchBrowserAndUrl(Constants.ADMIN_URL);
login(Constants.ADMIN_USER_NAME, Constants.ADMIN_USER_PASSWORD);
}
if(userType.equals("Customer")) {
launchBrowserAndUrl(Constants.CUSTOMER_TEST_URL);
login(Constants.CUSTOMER_USER_NAME, Constants.CUSTOMER_USER_PASSWORD);
}
}
#AfterMethod
public void tearDown() {
TestDriver.getDriver().quit();
}
}
public class AssignEditDeleteRoleAccessibilityTest extends BaseClass {
CreateUser newUser = new CreateUser();
RoleAssignmentAccessValidation roleAccessValidation = new RoleAssignmentAccessValidation();
#DataProvider(name = "AssignEditDeleteRoleAccessibilityTest")
public static Object[] roleNames() {
return new Object[] {Constants.AGENCY_ASSISTANT_ROLE_NAME, Constants.OPS_MANAGER_ROLE_NAME};
}
#Test ( priority=1, dataProvider = "AssignEditDeleteRoleAccessibilityTest")
public void assignRoleAccessTest(String roleName) {
newUser.createUserAssignRoleAndLogin(roleName);
boolean isAssignRoleOptionAvailable =roleAccessValidation.assignRoleAccess();
assertEquals(isAssignRoleOptionAvailable, false);
}
}
Now I am getting error:
FAILED CONFIGURATION: #BeforeMethod launchBrowserAndLogin
org.testng.TestNGException:
Can inject only one of <ITestContext, XmlTest, Method, Object[], ITestResult> into a #BeforeMethod annotated launchBrowserAndLogin.
If this were my code, I would split up BaseClass into AdminClass and CustomerClass -- this will both solve the issue, and also help organize the tests a little better, because now you will be aware if the scenario under test is either Customer or Admin view based on which class the test case class extends:
public class CustomerClass {
public CustomerClass() {
}
#BeforeMethod
public void launchBrowserAndLogin() {
launchBrowserAndUrl(Constants.CUSTOMER_TEST_URL);
login(Constants.CUSTOMER_USER_NAME, Constants.CUSTOMER_USER_PASSWORD);
}
#AfterMethod
public void tearDown() {
TestDriver.getDriver().quit();
}
}
And Admin class:
public class AdminClass{
public AdminClass() {
}
#BeforeMethod
public void launchBrowserAndLogin() {
launchBrowserAndUrl(Constants.ADMIN_URL);
login(Constants.ADMIN_USER_NAME, Constants.ADMIN_USER_PASSWORD);
}
#AfterMethod
public void tearDown() {
TestDriver.getDriver().quit();
}
}
Then, your test case class can look like this:
public class AssignEditDeleteRoleAccessibilityTest extends CustomerClass{ // or AdminClass
CreateUser newUser = new CreateUser();
RoleAssignmentAccessValidation roleAccessValidation = new RoleAssignmentAccessValidation();
#DataProvider(name = "AssignEditDeleteRoleAccessibilityTest")
public static Object[] roleNames() {
return new Object[] {Constants.AGENCY_ASSISTANT_ROLE_NAME, Constants.OPS_MANAGER_ROLE_NAME};
}
#Test ( priority=1, dataProvider = "AssignEditDeleteRoleAccessibilityTest")
public void assignRoleAccessTest(String roleName) {
newUser.createUserAssignRoleAndLogin(roleName);
boolean isAssignRoleOptionAvailable =roleAccessValidation.assignRoleAccess();
assertEquals(isAssignRoleOptionAvailable, false);
}
}
This will solve your error, but I recognize this also a matter of opinion & personal design preference -- the concept of a test fixture (which is what BaseClass / AdminClass / CustomerClass each represent) can be implemented in many different ways. I personally believe having a fixture for each "starting" scenario is better in terms of organization and maintainability -- if AdminClass ever becomes more complex, this code will be out of the way from CustomerClass.
Another alternative would be to keep BaseClass, but remove the #BeforeMethod and launchBrowserAndLogin() method. Then, you can write CustomerClass and AdminClass to extend BaseClass (so that the #AfterMethod is inherited). Then, CustomerClass and AdminClass() can implement their own versions of launchBrowserAndLogin(), and the test case class would still look the same as this sample.
There are other approaches to resolve this as well, it's just a matter of personal preference in terms of design and maintainability.
Even if this is not your preferred answer, hopefully this at least gives you an alternative approach for future thought.
What you are trying to do won't be as straightforward to achieve. The Data-Provider feeds the #Test method and the #BeforeMethod method runs before the Test Method, so sending a parameter from the second method to the first one to run won't be possible.
Maybe helping yourself with an ITestListener you can work something out.
For more information on what you can parameterize in your #BeforeMethod, refer to the link your error is telling to look at:
https://testng.org/doc/documentation-main.html#native-dependency-injection
There you have listed the possible things it can receive.
You need to have your BaseClass implement org.testng.IHookable and then have the run() method invoke your launchBrowserAndLogin() method.
Here's how your modified base class will look like:
import java.lang.reflect.Method;
import org.testng.IHookCallBack;
import org.testng.IHookable;
import org.testng.ITestResult;
import org.testng.annotations.AfterMethod;
public class BaseClass implements IHookable {
#Override
public void run(IHookCallBack callBack, ITestResult testResult) {
Object[] parameters = testResult.getParameters();
String userType = parameters[0].toString();
launchBrowserAndLogin(userType);
callBack.runTestMethod(testResult);
}
public void launchBrowserAndLogin(String userType) {
if (userType.equals("Admin")) {
System.err.println("Launching Admin flow");
launchBrowserAndUrl(Constants.ADMIN_URL);
login(Constants.ADMIN_USER_NAME, Constants.ADMIN_USER_PASSWORD);
}
if (userType.equals("Customer")) {
System.err.println("Launching Customer flow");
launchBrowserAndUrl(Constants.CUSTOMER_TEST_URL);
login(Constants.CUSTOMER_USER_NAME, Constants.CUSTOMER_USER_PASSWORD);
}
}
#AfterMethod
public void tearDown(Method method) {
//include your tear down logic here
System.err.println("tearDown() for " + method.getName());
}
public void launchBrowserAndUrl(String url) {
//logic goes here
}
public void login(String username, String password) {
//logic goes here
}
}
Related
I have a class, say SimpleClass, that has two functions with the same name and the same number of parameters but different parameter types. Now I assume mocking their return values should be as using two when statements with the appropriate matchers but instead when I attempt that I get the following error:
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Misplaced argument matcher detected here:
-> at mocks.MockTest.whenMethodsHaveSimilarSignatures(MockTest.java:28)
-> at mocks.MockTest.whenMethodsHaveSimilarSignatures(MockTest.java:28)
Here's a sample of what I'm attempting:
public class SimpleClass {
public boolean doWork(String value, String name) {
return false;
}
public boolean doWork(Integer value, String name) {
return true;
}
}
#RunWith(MockitoJUnitRunner.class)
public class MockTest {
private SimpleClass thing;
#Before
public void setup() {
thing = new SimpleClass();
}
#Test
public void whenMethodsHaveSimilarSignatures() {
when(thing.doWork(anyString(), anyString())).thenReturn(true);
when(thing.doWork(any(Integer.class), anyString())).thenReturn(false);
assertThat(thing.doWork("one", "name")).isTrue();
assertThat(thing.doWork(1, "name")).isFalse();
}
}
While I'm not a wizard at Mockito I've been using it for a while and never encountered this issue. Thoughts? I'm using Mockito-Core v2.2.9
You should not use any(Object.class) while stubbing overloaded methods because both String and Integer are child classes of Object, so specify the particular arguments during stubbing.You can also use ArgumentMatchers
when(thing.doWork(ArgumentMatchers.anyString(), ArgumentMatchers.anyString())).thenReturn(true);
when(thing.doWork(ArgumentMatchers.any(Integer.class), anyString())).thenReturn(false);
And also you are not mocking the SimpleClass
#RunWith(MockitoJUnitRunner.class)
public class MockTest {
private SimpleClass thing = Mockito.mock(SimpleClass.Class);
#Before
public void setup() {
MockitoAnnotations.initMocks(this); // need to enable these annotations programmatically
}
#Test
public void whenMethodsHaveSimilarSignatures() {
when(thing.doWork(anyString(), anyString())).thenReturn(true);
when(thing.doWork(any(Integer.class), anyString())).thenReturn(false);
//or
when(thing.doWork(ArgumentMatchers.anyString(), ArgumentMatchers.anyString())).thenReturn(true);
when(thing.doWork(ArgumentMatchers.any(Integer.class), anyString())).thenReturn(false);
assertThat(thing.doWork("one", "name")).isTrue();
assertThat(thing.doWork(1, "name")).isFalse();
}
}
My class structure is as follows:
public class MyParentClass {
void doSomethingParent() {
System.out.println("something in parent");
}
}
public class MyClass extends MyParentClass {
protected String createDummyRequest(Holder myHolder) {
//...
super.doSomethingParent();//I want to avoid this
//...
callingDB();
return "processedOutput";
}
private void callingDB() {
System.out.println("Calling to DB");
}
}
Then my unit test:
public class UnitTest {
public void testCreateDummyRequest() {
//create my mock holder
Holder mockHolder = new Holder();
MyClass mockObj = Mockito.mock(MyClass.class);
//mock doSomethingParent()
//mock callingDB()
//as mockObj is a fully mock, but I need to run my real method
//Mockito.when(mockObj.createDummyRequest(mockHolder)).thenCallRealMethod();
mockObj.createDummyRequest(mockHolder);
//Problem: doSomethingParent() is getting called though I have mocked it
}
}
How do I prevent the calling of the super.doSomethingParent() in my method? (method which I am writing my test)
With this class structure mocking and testing is real hard. If possible, I'd advice to change the structure as in mist cases a class structure that's hard to mock and test is equally hard to extend and maintain.
So if you could change your class structure to something similar to:
public class MyClass {
private DoSomethingProvider doSomethingProvider;
private DbConnector dbConnector;
public MyClass (DoSomethingProvider p, DbConnector c) {
doSomethingProvicer = p;
dbConnector = c;
}
protected String createDummyRequest(Holder myHolder){
//...
doSomethingProvider.doSomethingParent();
//...
dbConnector.callingDB();
return "processedOutput";
}
}
Then you could easily create your instance with mocks of DoSomethingProvider and DbConnector and voila....
If you can't change your class structure you need to use Mockito.spy instead of Mockito.mock to stub specific method calls but use the real object.
public void testCreateDummyRequest(){
//create my mock holder
Holder mockHolder = new Holder();
MyClass mockObj = Mockito.spy(new MyClass());
Mockito.doNothing().when(mockObj).doSomething();
mockObj.createDummyRequest(mockHolder);
}
Note: Using the super keyword prevents Mockito from stubbing that method call. I don't know if there is a way to stub calls to super. If possible (as in you didn't override the parent method in your class), just ommit the keyword.
I faced similar issue, so I find out that using spy() can hepld.
public class UnitTest {
private MyClass myObj;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
myObj= spy(new MyClass());
}
#Test
public void mockedSuperClassMethod(){
doNothing().when((MyParentClass )myObj).doSomethingParent();
//...
}
}
This approach works for me.
I found another approach, which turned out to be very useful in my case.
In the case I had, I needed to create a new class extending another, which included a very complex (legacy code) protected final method. Due to the complexity, it wasn't really possible to refactor to use composition, so here's what I came up with.
Let's say I have the following:
abstract class Parent {
public abstract void implementMe();
protected final void doComplexStuff( /* a long parameter list */) {
// very complex legacy logic
}
}
class MyNewClass extends Parent {
#Override
public void implementMe() {
// custom stuff
doComplexStuff(/* a long parameter list */); // calling the parent
// some more custom stuff
}
}
Here's how I rearranged this code:
abstract class Parent {
public abstract void implementMe();
protected final void doComplexStuff( /* a long parameter list */) {
// very complex legacy logic
}
}
interface ComplexStuffExecutor {
void executeComplexStuff(/* a long parameter list, matching the one from doComplexStuff */);
}
class MyNewClass extends Parent {
private final ComplexStuffExecutor complexStuffExecutor;
MyNewClass() {
this.complexStuffExecutor = this::doComplexStuff;
}
MyNewClass(ComplexStuffExecutor complexStuffExecutor) {
this.complexStuffExecutor = complexStuffExecutor;
}
#Override
public void implementMe() {
// custom stuff
complexStuffExecutor.doComplexStuff(/* a long parameter list */); // either calling the parent or the injected ComplexStuffExecutor
// some more custom stuff
}
}
When creating instance of MyNewClass for "production" purposes, I can use the default constructor.
When writing unit tests, however, I'd use the constructor, where I can inject ComplexStuffExecutor, provide a mock there and only test my custom logic from MyNewClass, i.e.:
class MyNewClassTest {
#Test
void testImplementMe() {
ComplexStuffExecutor complexStuffExecutor = Mockito.mock(ComplexStuffExecutor.class);
doNothing().when(complexStuffExecutor).executeComplexStuff(/* expected parameters */);
MyNewClass systemUnderTest = new MyNewClass(complexStuffExecutor);
// perform tests
}
}
At first glance, it seems like adding some boilerplate code just to make the code testable. However, I can also see it as an indicator of how the code should actually look like. Perhaps one day someone (who would find courage and budget ;) ) could refactor the code e.g. to implement the ComplexStuffExecutor with the logic from doComplexStuff from Parent, inject it into MyNewClass and get rid of inheritance.
Here is how it can be done
public class BaseController {
public void method() {
validate(); // I don't want to run this!
}
}
public class JDrivenController extends BaseController {
public void method(){
super.method()
load(); // I only want to test this!
}
}
#Test
public void testSave() {
JDrivenController spy = Mockito.spy(new JDrivenController());
// Prevent/stub logic in super.method()
Mockito.doNothing().when((BaseController)spy).validate();
// When
spy.method();
// Then
verify(spy).load();
}
Source: https://blog.jdriven.com/2013/05/mock-superclass-method-with-mockito/
I have an abstract method checkStatus() which has implementations in Checker.java class. But when I execute the Junit test case on abstract class method validate() that in-turn calls checkStatus(), fails due to missing spring dependency in Checker.java class.
Details provided below.
Abstract class:
public abstract class MyAbstractClass
{
protected abstract boolean checkStatus();
public boolean validate()
{
//Some code
return checkStatus();
}
}
Implementation class:
public class Checker extends MyAbstractClass
{
#Autowired
private StatusHelper helper;
public void setHelper(StatusHelper helper){
this.helper = helper;
}
#Override
public boolean checkStatus() throws Exception{
if(null == helper){
throw new Exception("Helper is null");
}
return helper.validateStatus();
}
}
JUnit test:
class AbstractClassTest
{
MyAbstractClass absClass = Mockito.mock(Checker.class, Mockito.CALLS_REAL_METHODS);
#Test
public void testStatusOfChecker()throws Exception {
boolean status = absClass.validate();
assertEquals(status, true);
}
}
I believe I can inject the helper object manually like the following
Checker check = mock(Checker.class);
StatusHelper helper = mock(StatusHelper.class);
check.setHelper(helper);
but the problem here is, I cannot inject directly to absClass object as the setHelper() is not inherited.
I can instead write test case directly to subclass, but I needed this way to test some other functionality in validate() method of abstract class.
Can someone help me how to set helper object to the sub class or is there different way to do it in Junit? Any help or links that contain relevant info is highly appreciable.
Thanks,
The only way to test an abstract class is by testing an implementation (which could be an anonymous class).
public class AbstractClassTest {
#Test
public void testStatusOfChecker() throws Exception {
MyAbstractClass object = new MyAbstractClass() {
protected boolean checkStatus() {
return true; //this is the place to provide the expected value
}
}
boolean status = absClass.validate();
assertEquals(status, true);
}
}
If you want to test the Checker implementation then you must not mock it.
public class CheckerTest {
#Test
public void test() {
StatusHelper helper = mock(StatusHelper.class);
Checker checker = new Checker();
checker.setHelper(helper);
when(helper.validate()).thenReturn(true);
boolean status = checker.validate();
assertEquals(status, true);
}
}
By the way I strongly recommend to use constructor injection (see Why field injection is evil). The test would then look like this
public class CheckerTest {
#Test
public void test() {
StatusHelper helper = mock(StatusHelper.class);
Checker checker = new Checker(helper);
when(helper.validate()).thenReturn(true);
boolean status = checker.validate();
assertEquals(status, true);
}
}
I have one TestCase class, whcih has 5 test methods. I can directly execute this class, then all the test methods will be executed. This is fine.
Suppose If I want to execute few test methods(but not all) and those methods will be decided based on certain condition at run time, what is the solution..?
To be more clear,
I have a TestCase class "MyTestCase"
public class MyTestCase extends TestCase
{
#Test
public void test1()
{
....
}
#Test
public void test2()
{
....
}
#Test
public void test3()
{
....
}
#Test
public void test4()
{
....
}
#Test
public void test5()
{
....
}
}
If I run this class, all the tests will be executed.
But my requirement is: I don't want all methods to be executed always. Sometimes 2 methods or 3 methods or 4 methods etc....
I have an XML file, which decides what test methods have to be executed.
Whatever is there in the XML file, only those test methods should be executed.
(I have a class, which reads the XML file to get the test method names.)
Is there any way to control no of test methods to be executed in a TestCase class at run time....?
I think I have to use TestSuite class. But I am not sure on how to use it exactly.
Can any one help in solving this problem...?
Thanks in advance,
Sunil
You can use a custom TestRunner to execute this.
public class SelectiveJunitRunner extends BlockJUnit4ClassRunner {
public SelectiveJunitRunner(Class<?> klass) throws InitializationError {
super(klass);
}
#Override
protected List<FrameworkMethod> computeTestMethods() {
//Inject ignore List
List<String> ignoreList = Arrays.asList("test2","test4");
List<FrameworkMethod> computeTestMethods = super.computeTestMethods();
List<FrameworkMethod> filteredList = new ArrayList<>();
for (FrameworkMethod frameworkMethod : computeTestMethods) {
if (!ignoreList.contains(frameworkMethod.getName()))
filteredList.add(frameworkMethod);
}
return filteredList;
}
}
Junit Test case
#RunWith(SelectiveJunitRunner.class)
public class SelectiveTest {
#Test
public void test1() {
System.out.println("1");
}
#Test
public void test2() {
System.out.println("2");
}
#Test
public void test3() {
System.out.println("3");
}
#Test
public void test4() {
System.out.println("4");
}
}
We have lots of selenium tests running through junit, and they all have a few steps which need to run before the actual tests. For this we have a parent TestCase class which has some #Before and #After methods in it.
Now, due to a new feature of our site I would like to parameterise part of this set up, I'd like to create a new annotation to put on some tests to indicate to the setup() method that the setup is slightly different, whilst allowing the others to use the default. So, is it possible to reflectively access the test method about to be run in an #Before method?
eg.
class SomeTest extends MyTestCase {
#Test
#Flavour(Red.class)
public void testRedFlavouredHomepage() {
testHomepage();
}
#Test
public void testBlueFlavouredHomepage() { // assuming Blue is my default flavour
testHomepage();
}
public void testHomepage() {
// test some stuff
}
}
You can do this using #Rule (with the later versions of JUnit >= 4.9). If you have a class which implements TestRule, specifically apply(), you can do extra things before your test gets run. The Description is passed to the apply method, which contains the annotations on your method:
Using #Deprecated as an example:
public class ExtraSetupTest {
#Rule
public TestRule moreSetup = new TestRule() {
public Statement apply(Statement base, Description description) {
return statement(base, description);
}
private Statement statement(final Statement base,
final Description description) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
if (description.getAnnotation(Deprecated.class) != null) {
System.out.println("more setup here");
}
base.evaluate();
}
};
}
};
#Test
public void noExtraSetup() {
System.out.println("noExtraSetup");
}
#Test
#Deprecated
public void withExtraSetup() {
System.out.println("withExtraSetup");
}
}
This produces as output:
noExtraSetup
more setup here
withExtraSetup
I'd rather suggest to use different test classes for those 2 methods.
class MyTestCase {
#Before
public void setUp() {
/* Default setup */
}
public void testHomepage() {
// test some stuff
}
}
class MyRedTestCase extends MyTestCase {
#Before
public void setUp() {
super.setUp();
/* Red setup */
}
}
And then you can put your tests into 2 different classes extending from MyTestCase and MyRedTestCase respectively.
class BlueTest extends MyTestCase {
#Test
public void testBlueFlavouredHomepage() { // assuming Blue is my default flavour
testHomepage();
}
}
class RedTest extends MyRedTestCase {
#Test
public void testRedFlavouredHomepage() {
testHomepage();
}
}
You can do it another way as well, without introducing new classes. Declare an absract (or concrete with the default value) method in your parent class.
class MyTestCase {
protected abstract Flour getFlour();
}
And your child class will look like this
class SomeTest extends MyTestCase {
private Flour flour;
#Test
public void testRedFlavouredHomepage() {
flour = Flour.RED;
testHomepage();
}
#Test
public void testBlueFlavouredHomepage() { // assuming Blue is my default flavour
flour = Flour.BLUE;
testHomepage();
}
public void testHomepage() {
// test some stuff
}
protected abstract Flour getFlour() {
return flour;
}
}
I'd say the 1st solution is "cleaner"; even though you have to create additional classes, you don't include logic of different types in one class (like in the anti-pattern God object).