Powermock, mockStatic of UUID.getRandom works in test class but doesn't in the class tested - uuid

Strange case: using Powermock to mock out UUID.getRandom(). This works within the JUnit test class but when the class under test (a Filter, if that matters) calls UUID.getRandom, a unique UUID is produced.
Simple test case
#RunWith(PowerMockRunner.class)
#PrepareForTest({UUID.class})
public class MyTest {
private MyFilter filter;
#Before
public void setup() {
//The most convenient way to get a UUID, have also tried creating one manually
UUID uuid = UUID.randomUUID();
mockStatic(UUID.class);
PowerMockito.when(UUID.randomUUID()).thenReturn(uuid);
filter = new MyFilter();
}
#Test
public void testMyUUID() {
//This test works
assertEquals(UUID.randomUUID(), UUID.randomUUID());
}
#Test
public void testFilterUUID() {
//This test fails
assertEquals(UUID.randomUUID(), filter.getUUID());
}
}
Simple class being tested
public class MyFilter implements Filter {
public UUID getUUID() {
return UUID.randomUUID();
}
}
Pretty simple stuff, have done mocking like this before, just can't figure out why this case doesn't work.
Using Powermock version 1.5.

I believe UUID falls under the "system classes" category, so you need to prepare for test the class calling UUID.randomUUID()(related github issue)., thus changing to #PrepareForTest({MyFilter.class}) should fix things. The following works as expected with JUnit 4.4 & Powermock 1.5, as well as JUnit 4.12 and Powermock 1.7.3:
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyFilter.class)
public class MyTest {
private MyFilter filter;
#Before
public void setup() {
//The most convenient way to get a UUID, have also tried creating one manually
UUID uuid = UUID.randomUUID();
mockStatic(UUID.class);
PowerMockito.when(UUID.randomUUID()).thenReturn(uuid);
filter = new MyFilter();
}
#Test
public void testMyUUID() {
//This test works
assertEquals(UUID.randomUUID(), UUID.randomUUID());
}
#Test
public void testFilterUUID() {
//This test fails
assertEquals(UUID.randomUUID(), filter.getUUID());
}
}

The accepted solution that is mentioned here won't work if you have multiple tests that tries to mockStatic before the tests, since mockStatic method from Mockito does not automatically close after the test.
I wrote the below solution which handles multiple tests by using PowerMockito.mockStatic instead of Mockito.mockStatic:
#RunWith(PowerMockRunner.class)
#PrepareForTest({MyFilter.class, UUID.class})
#PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "javax.management.*"})
public class MyTest {
#Before
public void setup() {
UUID uuid = UUID.randomUUID();
PowerMockito.mockStatic(UUID.class);
PowerMockito.when(UUID.randomUUID()).thenAnswer((invocation) -> uuid);
filter = new MyFilter();
}
#Test
public void testMyUUID() {
//This test works
assertEquals(UUID.randomUUID(), UUID.randomUUID());
}
#Test
public void testFilterUUID() {
//This test fails
assertEquals(UUID.randomUUID(), filter.getUUID());
}
}
NOTE to how mockStatic is used from PowerMockito library not the Mockito.

Related

Selenium Webdriver C# - Running more than one test case in VS 2017 from Test Suite

I have been working on Page Object Framework which will have categorized test suites depending on the page. I have followed all steps in order to build a decent framework.
My each Unit Test, contains one method which follows simple steps. So far I have been able to create a few automated test cases. The issue began when I wanted to run more than one test case from the test suite. I have one chrome web driver instance which is in a separate class. Below is an example:
using System;
using System.Dynamic;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
namespace SystemUiAutomationTestFramework
{
public static class Browser
{
private static readonly IWebDriver _webDriver = new ChromeDriver(Properties.Settings.Default.ChromePathDriver);
public static IWebDriver WebDriver {
get { return _webDriver; }
}
public static ISearchContext Driver
{
get { return _webDriver; }
}
public static string Url
{
get { return _webDriver.Url; }
}
public static string Title
{
get { return _webDriver.Title; }
}
public static void Goto(string url)
{
_webDriver.Manage().Window.Maximize();
_webDriver.Url = url;
}
public static void Close()
{
_webDriver.Quit();
}
}
}
Each test case when it is run is independent and as good practice shows, there should be no test order implementation because it generates flows. I will place two examples which check simple login operation and login validation.
Below you can find a class for the login page:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.AccessControl;
using System.Text;
using System.Threading.Tasks;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.PageObjects;
using OpenQA.Selenium.Support.UI;
namespace SystemUiAutomationTestFramework
{
public class LoginPage
{
static string Url = "http://..";
private static string LoginUrl = "http://...";
private static string PageTitle = "System title page";
private static string LoginPlaceholder = "Login";
private static string PswdPlaceholder = "Password";
private static string ButtonText = "Sign in";
private static string ErrorMessage = "Wrong login or password";
/* LoginPage Elements */
[FindsBy(How = How.Id, Using = "inputLogin")]
private IWebElement inputLogin;
[FindsBy(How = How.Id, Using = "inputPassword")]
private IWebElement inputPassword;
[FindsBy(How = How.TagName, Using = "button")]
private IWebElement loginButton;
[FindsBy(How = How.ClassName, Using = "errorMsg")]
private IWebElement errorMessage;
/*----------------------------------------*/
public void Goto()
{
Browser.Goto(Url);
}
public bool IsAtLoginPage()
{
return Browser.Url == LoginUrl;
}
public bool IsAtLoginPageTitle()
{
return Browser.Title == PageTitle;
}
public bool IsAtLoginField()
{
return inputLogin.GetAttribute("placeholder") == LoginPlaceholder;
}
public bool IsAtPswdField()
{
return inputPassword.GetAttribute("placeholder") == PswdPlaceholder;
}
public bool IsAtLoginButton()
{
return loginButton.Text == ButtonText;
}
public void InputCredentials(string userName, string userPassword)
{
inputLogin.SendKeys(userName);
inputPassword.SendKeys(userPassword);
loginButton.Click();
}
public void WaitErrorMessage()
{
WebDriverWait wait = new WebDriverWait(Browser.WebDriver, TimeSpan.FromSeconds(10));
wait.Until(ExpectedConditions.VisibilityOfAllElementsLocatedBy(By.ClassName("errorMsg")));
}
public bool IsAtErrorMessage()
{
return errorMessage.Text == ErrorMessage;
}
public void ReportPageSuccessLogin()
{
Console.WriteLine("Application Url checked");
Console.WriteLine("Application Title checked");
Console.WriteLine("Login Field present");
Console.WriteLine("Password Field checked");
Console.WriteLine("Sign in button checked");
Console.WriteLine("Login ssuccess");
}
public void ReportPageValidationTest()
{
ReportPageSuccessLogin();
Console.WriteLine("Fake Credentials entered");
Console.WriteLine("Login Button Pressed");
Console.WriteLine("Login or Password validation message displayed: " + errorMessage.Displayed);
}
}
}
I also have an API class for Pagefactoring. As an example:
public static class Pages
{
public static LoginPage LoginPage
{
get
{
var loginPage = new LoginPage();
PageFactory.InitElements(Browser.Driver, loginPage);
return loginPage;
}
}
Now for the test cases, below an example when a user is on the login page, all elements are displaed, logs into the system, system checks if the user has logged into and closes the instance.
using System;
using System.Runtime.Remoting.Channels;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SystemUiAutomationTestFramework;
namespace TestSuite.LoginPage
{
[TestClass]
public class LoginPageTest
{
[TestMethod]
public void Can_Go_LoginPage()
{
Pages.LoginPage.Goto();
Assert.IsTrue(Pages.LoginPage.IsAtLoginPage());
Assert.IsTrue(Pages.LoginPage.IsAtLoginPageTitle());
Assert.IsTrue(Pages.LoginPage.IsAtLoginField());
Assert.IsTrue(Pages.LoginPage.IsAtPswdField());
Assert.IsTrue(Pages.LoginPage.IsAtLoginButton());
Pages.LoginPage.InputCredentials(SettingsService.Username, SettingsService.Userpassword);
Pages.HomePage.IsAtHomePage();
Pages.LoginPage.ReportPageSuccessLogin();
}
[TestCleanup]
public void CleanUp()
{
Browser.Close();
}
}
}
The other one just validates the login page by providing fake login and password and if the error message is correctly displayed the test case finishes also by closing the instance.
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SystemUiAutomationTestFramework;
namespace TestSuite.LoginPage
{
[TestClass]
public class LoginPageValidationTest
{
[TestMethod]
public void Can_Validate_LoginPage()
{
Pages.LoginPage.Goto();
Assert.IsTrue(Pages.LoginPage.IsAtLoginPage());
Assert.IsTrue(Pages.LoginPage.IsAtLoginPageTitle());
Assert.IsTrue(Pages.LoginPage.IsAtLoginField());
Assert.IsTrue(Pages.LoginPage.IsAtPswdField());
Assert.IsTrue(Pages.LoginPage.IsAtLoginButton());
Pages.LoginPage.InputCredentials("abcd.efgh", "test123");
Pages.LoginPage.WaitErrorMessage();
Assert.IsTrue(Pages.LoginPage.IsAtErrorMessage());
Pages.LoginPage.ReportPageValidationTest();
}
[TestCleanup]
public void CleanUp()
{
Browser.Close();
}
}
}
Now the issue happens when I try those two test cases from the Login Page Test Suite, one finishes as passed the other one as failed. From the error message, I understand that it is because the other test case is trying to use an instance of the Webdriver which is already running.
I would like to know your opinion/guides/solution how can I solve this problem. I apologize for the long post but I thought that if I place my code it will be easy for you to understand my issue.
Best regards and thank you for your answers or linking me to the topic which either a duplicate of my issue or there is a solution already for it.
I was able to solve the issue on my own. I have created an
property for my driver class and an Initialize method which is called each time a test class is called. Also refactored my code to be more flexible.

C# + WebDriver PageFactory + Nunit 3 Parallelizable

I have implemented the following setup in my automation framework:
C# Selenium webDriver
IObjectContainer
Specflow
Nunit 3 Parallelizable
Xpaths (and all selectors) are simply defined as 'private const string'
code sample HomePageSteps (working code):
[Binding]
public class HomePageSteps
{
private IWebDriver _driver;
public HomePageSteps(IWebDriver driver)
{
_driver = driver;
}
private const string LogoTwo = "//img[#alt='xpath']";
[Given(#"I navigation to site")]
public void GivenINavigationToSite()
{
_driver.Navigate().GoToUrl("http://website.com/");
_driver.FindElement(By.XPath(LogoTwo)).Click();
}
}
But I want to use the webDriver PageFactory attribute to handle my page objects. Which I have done / used in other projects that do Not use 'Nunit 3 Parallelizable'.
code example (NOT working code):
[Binding]
public class HomePageSteps
{
private IWebDriver _driver;
public HomePageSteps(IWebDriver driver)
{
_driver = driver;
}
[FindsBy(How = How.XPath, Using = "//img[#alt='xpath']")]
public IWebElement logo { get; set; }
[Given(#"I navigation to site")]
public void GivenINavigationToSite()
{
_driver.Navigate().GoToUrl("http://website.com/");
logo.Click();
}
}
The problem here is that 'logo' is Null. And I'm not sure if this problem is related to a limitation of use ''Nunit 3 Parallelizable' with PageFactory, or with specflow, or something else in my design.
Can anyone please give some guidance?
The reason Page Factory would not initialize non-static driver is that it takes in Static driver. If The constructor for the page is defined like this :
ChromeDriverService service = ChromeDriverService.CreateDefaultService(startDirectory + #"\Drivers\", "chromedriver.exe");
IWebDriver Static driver = new ChromeDriver(Service);
public HomePageSteps()
{
PageFactory.InitElements(driver, this);
}
It would allow you to use the elements as you have defined them.
Please let me know if you have found any other work around to this.

testng how to dynamically set groups from Factory?

Before I setup a test class like the code below:
1. the Factory and test Dataprovider both used excel as the dataprovider.
2. In the Factory dataprovider table, it has a list of url
3. Each time, it will find one of the url in the factory dataprovider table, and run the test in each test methods..
public class Test {
WebDriver driver;
private String hostName;
private String url;
#Factory(dataProvider = "xxxx global variables", dataProviderClass = xxxx.class)
public GetVariables(String hostName, String url) {
this.hostName = hostName;
this.url = url;
}
#BeforeMethod
#Parameters("browser")
public void start(String browser) throws Exception {
driver = new FirefoxDriver();
driver.get(url);
Thread.sleep(1000);
}
#Test(priority = 10, dataProvider = "dataprovider Test A", dataProviderClass = xxx.class)
public void TestA(Variable1,
Variable2,Variable3) throws Exception {
some test here...
}
#Test(priority = 20, dataProvider = "dataprovider Test B", dataProviderClass = xxx.class)
public void TestB(Variable1,
Variable2,Variable3)
throws Exception {
some test here...
}
#AfterMethod
public void tearDown() {
driver.quit();
}
Now I want to dynamically assign different group for each test for different url. I am thinking add a variable 'flag' in the #Factory dataprovider:
#Factory(dataProvider = "xxxx global variables", dataProviderClass = xxxx.class)
public GetVariables(String hostName, String url, String flag) {
this.hostName = hostName;
this.url = url;
this.flag = flag;
}
That when flag.equals("A"), it will only run test cases in test groups={"A"}.
When flag.equals("B"), it will only run test cases in test groups ={"B"},
When flag.equals("A,B"), it will only run test cases in test groups ={"A","B"}
Is there any way I can do that?
Thank you!
TestNG groups provides "flexibility in how you partition your tests" but it isn't for conditional test sets. For that you simply use plain old Java.
You can use inheritance or composition (I recommend the latter, see Item 16: Favor composition over inheritance from Effective Java).
Either way the general idea is the same: use a Factory to create your test class instances dynamically creating the appropriate class type with the appropriate test annotations and/or methods that you want to run.
Examples:
Inheritance
import org.testng.annotations.Factory;
import org.testng.annotations.Test;
public class DemoTest {
#Factory
public static Object[] createTests() {
return new Object[]{
new FlavorATest(),
new FlavorBTest(),
new FlavorABTest()
};
}
/**
* Base test class with code for both A-tests and B-tests.
*
* Note that none of these test methods are annotated as tests so that
* subclasses may pick which ones to annotate.
*/
public static abstract class BaseTest {
protected void testA() {
// test something specific to flavor A
}
protected void testB() {
// test something specific to flavor B
}
}
// extend base but only annotate A-tests
public static class FlavorATest extends BaseTest {
#Test
#Override
public void testA() {
super.testA();
}
}
// extend base but only annotate B-tests
public static class FlavorBTest extends BaseTest {
#Test
#Override
public void testB() {
super.testB();
}
}
// extend base and annotate both A-tests and B-tests
public static class FlavorABTest extends BaseTest {
#Test
#Override
public void testA() {
super.testA();
}
#Test
#Override
public void testB() {
super.testB();
}
}
}
Composition
import org.testng.annotations.Factory;
import org.testng.annotations.Test;
public class DemoTest {
#Factory
public static Object[] createTests() {
return new Object[]{
new FlavorATest(),
new FlavorBTest(),
new FlavorABTest()
};
}
private static void testA() {
// test something specific to flavor A
}
private static void testB() {
// test something specific to flavor B
}
// only create A-test methods and delegate to shared code above
public static class FlavorATest {
#Test
public void testA() {
DemoTest.testA();
}
}
// only create B-test methods and delegate to shared code above
public static class FlavorBTest {
#Test
public void testB() {
DemoTest.testB();
}
}
// create A-test and B-test methods and delegate to shared code above
public static class FlavorABTest {
#Test
public void testA() {
DemoTest.testA();
}
#Test
public void testB() {
DemoTest.testB();
}
}
}
Your factory methods won't be as simple as you'll need to use your "flag" from your test data to switch off of and create instances of the appropriate test classes.

Selenium Webdriver_Java_How to Call Mutiple Class into One Class

I stuck at point i have one website for example (http://newtours.demoaut.com/) and for that i have created multiple classes likes:
App_Login(),
App_Dashboard(),
App_FliReservation(),
Cancel_Flight();
So want to call above all classes into single class .
can someone guide me on these.
Script sample
App_Login() class
public class App_login {
public static void main(String[] args) {
// TODO Auto-generated method stub
WebDriver driver= new FirefoxDriver();
driver.get("http://newtours.demoaut.com/");
}
}
and i want to call above class into following class
public class Mercurywebapp {
#Test
public void supp_onboarding() throws Exception {
App_Login();
}
public void App_Login() {
// TODO Auto-generated method stub
}
}
when i run above class (i.e.Mercurywebapp) then getting blank screen
Create another instances of all the Classes in the MercuryWebapp
Depends on the access modifiers for the classes
e.g
App_Login testObject = new App_Login();

Unable to mock GAE userservice

I am trying to mock the gae user service for writing unit tests and couldn't get the following code to work.
My test class is as below.
public class AuthenticationTest {
private final LocalServiceTestHelper helper =
new LocalServiceTestHelper(new LocalUserServiceTestConfig())
.setEnvIsAdmin(true).setEnvIsLoggedIn(true)
.setEnvEmail("test#example.com");
#Before
public void setUp() {
helper.setUp();
}
#After
public void tearDown() {
helper.tearDown();
}
#Test
public void testIsAdmin() {
UserService userService = UserServiceFactory.getUserService();
assertTrue(userService.isUserAdmin());
String email = userService.getCurrentUser().getEmail();
assertEquals(email, "test#example.com");
}
}
I find that userService.getCurrentUser() always returns null.
Most of the code is taken from the example in developers.google.com. The only thing I added is call to .setEnvEmail("test#example.com")
Any help would be appreciated.
Thanks,
Sathya
in order to mock email, the auth domain also needs to be mocked, just add
.setEnvAuthDomain("example.com");
to your helper initialisation or in #Before method post initialise and it will work fine.
hope it helps

Resources