How could you write a salesforce test class for a simple user-agent lookup? - testing

I'm looking to write a test for a function that just returns a value - that's it. I'm not sure how you could do that. I'm under the impression you have to use system.assert or something. New to SFDC, but have programmed in many other languages. Here's some sample code:
static String getBrowserName()
{
String userAgent = ApexPages.currentPage().getHeaders().get('User-Agent');
if (userAgent.contains('iPhone'))
return 'iPhone-Safari';
if (userAgent.contains('Salesforce'))
return 'Salesforce';
if (userAgent.contains('BlackBerry'))
return 'BlackBerry';
if (userAgent.contains('Firefox'))
return 'Firefox';
if (userAgent.contains('Safari'))
return 'Safari';
if (userAgent.contains('internet explorer'))
return 'ie';
return 'other';
}
How can you obtain 100% test coverage for that?

While Salesforce's lack of a mocking framework is infuriating because of the hoops you have to jump through when testing things like page controllers, it's important to think about what you want to test here. Assuming that what you specifically want to test is that given the user agent strings your code returns the appropriate string, then I think something like the following should work:
static String getBrowserName(string userAgentStringToTest)
{
PageReference pageRef = getPageReference(userAgentStringToTest);
String userAgent = getUserAgent(pageRef);
...
}
PageReference getPageReference(string userAgentStringToTest)
{
if(userAgentStringToTest.Length == 0)
{
return ApexPages.currentPage();
}
else
{
PageReference pageRef = new PageReference('someURL');
pageRef.getHeaders().put('User-Agent', userAgentStringToTest);
return pageRef;
}
}
String getUserAgent(PageReference pageRef)
{
pageRef.getHeaders().get('User-Agent');
}
You would then call the getBrowserName method with the empty string in your production code and with the string you want to test in your test code.
There are a few different flavours to this of course - you could overload the methods and have a parameterless method for the main code and a parameterized method for testing. It's not ideal, but I don't know of another way to do it on the force.com platform currently.
EDIT: Just for completeness, I'm adding sample tests to clarify things. My example showed how to refactor the production code to make it testable, but did not give an example of how to write a test like the OP asked for.
Your tests would look something like this:
static testMethod void checkIPhoneBrowser()
{
String actualBrowserName = getBrowserName('string containing iPhone somewhere');
String expectedBrowserName = 'iPhone-Safari';
System.assertEquals(expectedBrowserName , actualBrowserName );
}
static testMethod void checkIEBrowser()
{
String actualBrowserName = getBrowserName('string containing internet explorer somewhere');
String expectedBrowserName = 'ie';
System.assertEquals(expectedBrowserName , actualBrowserName );
}
...

Related

How to unit test azure function using Xunit and Moq

I am very new to unit tests and recently started learning it from various online resources.
But still it confuses me when I need to implement it in my code.
For the given image which I have attached here, could anyone of you suggest me how should I start or where to start?
This is Azure function which I will be creating unit test for, framework/library I would prefer is Xunit and moq.
As mentioned in a comment, a good place to start when unit testing is looking at your code and identifying the different "paths" it can take and what the result of that path will be.
if (inventoryRequest != null)
{
// path 1
await _inventoryService.ProcessRequest(inventoryRequest);
_logger.LogInformation("HBSI Inventory Queue trigger function processed.");
}
else
{
// path 2
_logger.LogInformation("Unable to process HBSI Rate plan Queue.");
}
In your code, because of your if statement, there are 2 possible paths which will end in 2 different results = 2 unit tests.
Now you can start creating your unit tests but first you need to find out what you need to set up to be able to trigger your code.
private readonly ILogger _logger;
private readonly IInventoryService _inventoryService;
public InventoryServiceBusFunction(ILogger logger, IInventoryService inventoryService)
{
_logger = logger;
_inventoryService = inventoryService;
}
You have some dependencies being passed into your constructor with interfaces - great, this means we can mock them. We want to mock dependencies in unit tests because we want to control their behaviour for the tests. Also, mocking the dependencies negates any "real" behaviour the dependency might be performing i.e. database operations, API calls etc.
Using Moq we can mock the objects like so:
public class InventoryServiceBusFunctionTests
{
private readonly Mock<ILogger> _mockLogger = new Mock<ILogger>();
private readonly Mock<IInventoryService> _mockInventoryService = new Mock<IInventoryService>();
...
We will use these mocks later to make verifications on behaviour we expect to happen.
Next, we need to create an instance of the actual class we want to test.
// using a constructor in the test class will run this code before each test
public InventoryServiceBusFunctionTests()
{
// pass the mocked objects to initialize class
_inventoryServiceBusFunction = new InventoryServiceBusFunction(_mockLogger.Object, _mockInventoryService.Object);
}
Now that we have an instance of the InventoryServiceBusFunction class, we can use any of the public properties/methods in our tests.
[Fact]
public async Task GivenInventoryRequest_WhenFunctionRuns_ThenInventoryServiceProcessesRequest()
{
Now, remembering the paths from earlier, we can start to create the test cases. We can take the first path and create a [Fact] for it. You want to give your test case a meaningful name. I usually use the style of Given_When_Then to describe what is expected to happen.
Next, I usually add 3 comment sections to my test case:
// arrange
// act
// assert
This allows me to clearly see which parts of the test are doing what.
// act
await _inventoryServiceBusFunction.Run(inventoryRequest);
Next, I would fill in the \\ act section because this will tell me (via Intellisense) what I need to arrange. e.g. above, when hovering my mouse over the Run method, I can see that I need to pass an instance of InventoryRequest.
// arrange
var inventoryRequest = new InventoryRequest
{
Name = "abc123",
Quantity = 2,
Tags = new List<string>
{
"foo"
}
};
In the \\ arrange section, initialize an instance of the InventoryRequest class and set the properties. This can be any data as we aren't really interested in the data itself but more what happens when the code runs.
if (inventoryRequest != null)
{
// path 1
await _inventoryService.ProcessRequest(inventoryRequest);
_logger.LogInformation("HBSI Inventory Queue trigger function processed.");
}
Lastly, the \\ assert section. Here, we want to make assertions on what we expect to happen given the set up of the test. So given the InventoryRequest is not null, we expect the if to evaluate to true and we expect the _inventoryService.ProcessRequest(inventoryRequest) method to be executed.
// assert
_mockInventoryService
.Verify(x => x.ProcessRequest(It.Is<InventoryRequest>(ir => ir.Name == inventoryRequest.Name
&& ir.Quantity == inventoryRequest.Quantity
&& ir.Tags.Contains(inventoryRequest.Tags[0]))));
In Moq, we can use the .Verify() method on the mock object to assert that the method was called. We can use the It.Is<T> syntax to make assertions on the data that is passed to the method.
Here is the full test case for path 1:
[Fact]
public async Task GivenInventoryRequest_WhenFunctionRuns_ThenInventoryServiceProcessesRequest()
{
// arrange
var inventoryRequest = new InventoryRequest
{
Name = "abc123",
Quantity = 2,
Tags = new List<string>
{
"foo"
}
};
// act
await _inventoryServiceBusFunction.Run(inventoryRequest);
// assert
_mockInventoryService
.Verify(x => x.ProcessRequest(It.Is<InventoryRequest>(ir => ir.Name == inventoryRequest.Name
&& ir.Quantity == inventoryRequest.Quantity
&& ir.Tags.Contains(inventoryRequest.Tags[0]))));
}
Then for path 2, you are setting up the test so that the else condition is executed.
[Fact]
public async Task GivenInventoryRequestIsNull_WhenFunctionRuns_ThenInventoryServiceDoesNotProcessRequest()
{
// arrange
InventoryRequest inventoryRequest = null;
// act
await _inventoryServiceBusFunction.Run(inventoryRequest);
// assert
_mockInventoryService
.Verify(x => x.ProcessRequest(It.IsAny<InventoryRequest>()), Times.Never);
}
Note - in the \\ assert here, I am asserting that the await _inventoryService.ProcessRequest(inventoryRequest) method is never called. This is because you want the test to fail in this scenario as the method should only be executed in the if condition. You may also choose to verify that the logger method is called with the correct message.

How to write an APEX #test for a picklist method?

I was searching for answears but I couldn't find it. It might be a beginner question, anyhow I am stuck.
What I am trying to write is a test in Apex. Basically the Apex code gets field names from one specific object. Each fieldname will be shown in a picklist, one after the other (that part is a LWC JS and HTML file).
So, only want to test the Apex for the moment.
I don't know how to check that a list contains 2 parameters, and those parameters are object and field. Then the values are correctly returned, and I don't know how to continue.
Here's the Apex class with the method, which I want to test.
public without sharing class LeadController {
public static List <String> getMultiPicklistValues(String objectType, String selectedField) {
List<String> plValues = new List<String>();
Schema.SObjectType convertToObj = Schema.getGlobalDescribe().get(objectType);
Schema.DescribeSObjectResult objDescribe = convertToObj.getDescribe();
Schema.DescribeFieldResult objFieldInfo = objDescribe.fields.getMap().get(selectedField).getDescribe();
List<Schema.PicklistEntry> picklistvalues = objFieldInfo.getPicklistValues();
for(Schema.PicklistEntry plv: picklistvalues) {
plValues.add(plv.getValue());
}
plValues.sort();
return plValues;
}
}
I welcome any answers.
Thank you!
This might be a decent start, just change the class name back to yours.
#isTest
public class Stack73155432Test {
#isTest
public static void testHappyFlow(){
List<String> picklistValues = Stack73155432.getMultiPicklistValues('Lead', 'LeadSource');
// these are just examples
System.assert(!picklistValues.isEmpty(), 'Should return something');
System.assert(picklistValues.size() > 5, 'At least 5 values? I dunno, whatever is right for your org');
System.assert(picklistValues[0] < picklistValues[1], 'Should be sorted alphabetically');
System.assert(picklistValues.contains('Web'), 'Or whatever values you have in the org');
}
#isTest
public static void testErrorFlow(){
// this is actually not too useful. You might want to catch this in your main code and throw AuraHandledExceptions?
try{
Stack73155432.getMultiPicklistValues('Account', 'AsdfNoSuchField');
System.assert(false, 'This should have thrown');
} catch(NullPointerException npe){
System.assert(npe.getMessage().startsWith('Attempt to de-reference a null object'), npe.getMessage());
}
}
}

Serenity BDD screenplay verify multiple text elements on the webpage

How do I verify multiple text elements and links in the bdd using Serenity BDD ?
I am using below code but using this approach i have to write same copy of code for every element on the webpage which is timeconsuming, is there any alternate way to parametrize and verify values
private static final String APIBUILDER = "app-data-api-card .card-header";
#Subject("the displayed notebook")
public static class APIBUILDER implements Question<String> {
#Override
public String answeredBy(Actor actor) {
return BrowseTheWeb.as(actor).findBy(APIBUILDER).getText();
}
public static Question<String> value() { return new APIBUILDER(); }
You can use the Ensure library
static By FIRST_NAME_FIELD = By.id("first_name");
static By LAST_NAME_FIELD = By.id("last_name");
actor.attemptsTo(
Ensure.that(FIRST_NAME_FIELD).text().isEqualTo("Foo")
Ensure.that(LAST_NAME_FIELD).text().isEqualTo("Bar")
);
If you want soft assertions, you could also do this:
Ensure.enableSoftAssertions();
actor.attemptsTo(
Ensure.that(FIRST_NAME_FIELD).text().isEqualTo("Foo")
Ensure.that(LAST_NAME_FIELD).text().isEqualTo("Bar")
);
Ensure.reportSoftAssertions();
Actually the example with soft assertions doesn't work as intended. When the first check fails then the next one is not executed.

How to write a PHPUnit test for a SOAP server?

UPD. Sorry, guys.
I have an application that acts as a SOAP server, how do I write a PHPUnit test to test it?
SOAP extension is reading data from PHP input stream. You just provide your own data there and create some integration/unit tests for your API.
Take a look at the signature of SoapServer::handle() method. It takes as an argument a string which is a request itself. This parameter is optional and if you don't pass anything in, PHP will just read the data itself. But you can simply override it.
I used streams to do it. First you wrap the SoapServer with your own class like this:
class MyServer
{
/** \SoapServer */
private $soapServer;
public function __construct(\SoapServer $soapServer)
{
$this->soapServer = $soapServer;
}
public function handle(Psr\Http\Message\StreamInterface $inputStream): void
{
$this->soapServer->handle($inputStream->getContent());
}
}
Now you are ready to mock the request.
In your test you can do:
class MyTest extends TestCase
{
public function testMyRequest(): void
{
$mySoapServer = $this->createMySoapServer();
$request = $this->createRequest();
$mySoapServer->handle($request);
}
private function createRequest(): StreamInterface
{
$requestString = '<soap:Envelope></soap:Envelope>';
$fh = fopen('php://temp', 'rw');
fwrite($fh, $requestString);
fseek($fh, SEEK_SET);
return new Psr\Http\Message\StreamInterface\Stream($fh);
}
private function createMySoapServer(): MyServer
{
return new MyServer(new \SoapServer());
}
}
One thing to keep in mind - this test will generate output. You may want to test this output or ignore it. Depends on your use case.
Another side note. What you are asking for has really nothing to do with PHPUnit. It just a matter of designing your SOAP server correctly.
If you are wondering how to set up the stream when you have a live request, this is really simple:
$server->handle(new Psr\Http\Message\StreamInterface\Stream(fopen('php://input', 'r+')));

Combining dataproviders TestNG

I have read a few stackoverflow posts about combining dataproviders but I cant't get anything to work.
What I'm currently doing is a selenium test that takes screenshots of every language the site is translated to.
It simply clicks through every link while taking screenshots of it, then it switches the URL to another language and repeat.
My problem is when doing this I can't redirect my screenshots to a specific folder per "language test". To do this I need a second dataprovider, but I already have a dataprovider for this test method for running a different URL per test.
So I need to combine these two dataproviders somehow.
They currently look like this
public static Object [][] language(){
return new Object[][]{
{"https://admin-t1.taxicaller.net/login/admin.php?lang=en"},
{"https://admin-t1.taxicaller.net/login/admin.php?lang=sv"},
};
}
public static Object [][] directory(){
return new Object[][]{
{"screenshotsEnglish.dir"},
{"screenshotsSwedish.dir"},
};
}
In my test class I just want to reach these two by writing
driver.get(**url**);
// This is the screenshot method. Where "Directory" is written I decide where to save the screenshots
Properties settings = PropertiesLoader.fromResource("settings.properties");
String screenshotDir = settings.getProperty(**directory**);
screenShooter = new ScreenShooter(driver, screenshotDir, "en");
Hope I have made myself clear, appreciate all help!
Regards
public static Object[][] dp() {
return new Object[][]{
{
"https://admin-t1.taxicaller.net/login/admin.php?lang=en",
"screenshotsEnglish.dir"
},
{
"https://admin-t1.taxicaller.net/login/admin.php?lang=sv",
"screenshotsSwedish.dir"
}
};
}
#Test(dataProvider = "dp")
public void t(String url, String directory) {
driver.get(url);
Properties settings = PropertiesLoader.fromResource("settings.properties");
String screenshotDir = settings.getProperty(directory);
screenShooter = new ScreenShooter(driver, screenshotDir, "en");
/*...*/
}