Make an integration test of the dbContext - entity-framework

I am trying to do an integration test to test if my ApplicationDbContext is working properly. It is on a MVC core asp.net 3.1 application using entity framework and Pomelo.EntityFramework.MySql.
For the moment, I have just created the MVC application with ApplicationDbContext; An entity ; and I configured the database in startup.cs. At that time, I tested to migrate and update the database and it works.
After that, I added 2 projects in my solution for the unit test and the integration test, then adding the project reference on them. I did a simple test to use ApplicationDbContext but it doesn't work and I'm having trouble solving this problem.
If anyone has an idea on how to create this kind of test using xunit.
My project code is here: https://github.com/BeRoots/aspnetcore3.1-MVC-EF-MySQL
The integration test that I tryed to do is HERE

First, you will need to add the Pomelo.EntityFrameworkCore.MySql NuGet package to your weblab2 and XUnitIntegrationTestWeblab2 projects.
Then you need to reference your weblab2 project from your XUnitIntegrationTestWeblab2 project.
Your project will now compile, but your test will still fail.
Finally, you will need to setup your ApplicationDbContext instance, before using it.
I did this in form of a very simple example for the Application_DbContext_Should_Connect_To_MySql_Database test:
[Fact]
public void Application_DbContext_Should_Connect_To_MySql_Database()
{
// Arrange
var optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseMySql("server=127.0.0.1;port=3306;user=root;password=;database=so59888273", builder => builder
.ServerVersion(new Version(8, 0, 18), ServerType.MySql));
ApplicationDbContext dbContext = new ApplicationDbContext(optionsBuilder.Options);
bool expected = true;
// Act
bool result = dbContext.Database.CanConnect();
// Assert
Assert.Equal(expected, result);
}
Here is a patch containing all the changes:
diff --git a/XUnitIntegrationTestWeblab2/UnitTest2.Pomelo.EntityFramework.Core.MySql.ApplicationDbContextTest.cs b/XUnitIntegrationTestWeblab2/UnitTest2.Pomelo.EntityFramework.Core.MySql.ApplicationDbContextTest.cs
index 2c60ea3..0b058a5 100644
--- a/XUnitIntegrationTestWeblab2/UnitTest2.Pomelo.EntityFramework.Core.MySql.ApplicationDbContextTest.cs
+++ b/XUnitIntegrationTestWeblab2/UnitTest2.Pomelo.EntityFramework.Core.MySql.ApplicationDbContextTest.cs
## -1,4 +1,6 ##
using System;
+using Microsoft.EntityFrameworkCore;
+using Pomelo.EntityFrameworkCore.MySql.Infrastructure;
using weblab2.Data;
using Xunit;
## -6,18 +8,24 ## namespace XUnitIntegrationTestWeblab2
{
public class UnitTest2_Pomelo_EntityFramework_Core_MySql_ApplicationDbContextTest
{
- [Fact]
- public void Application_DbContext_Should_Connect_To_MySql_Database()
- {
- // Arrange
- ApplicationDbContext DbContext = new ApplicationDbContext();
- bool expected = true;
- // Act
- bool result = DbContext.Database.CanConnect();
+[Fact]
+public void Application_DbContext_Should_Connect_To_MySql_Database()
+{
+ // Arrange
+ var optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>()
+ .UseMySql("server=127.0.0.1;port=3306;user=root;password=;database=so59888273", builder => builder
+ .ServerVersion(new Version(8, 0, 18), ServerType.MySql));
- // Assert
- Assert.Equal(expected, result);
- }
+ ApplicationDbContext dbContext = new ApplicationDbContext(optionsBuilder.Options);
+ bool expected = true;
+
+ // Act
+ bool result = dbContext.Database.CanConnect();
+
+ // Assert
+ Assert.Equal(expected, result);
+}
+
[Fact]
public async void Application_DbContext_Should_Connect_To_MySql_Database_Async()
{
diff --git a/XUnitIntegrationTestWeblab2/XUnitIntegrationTestWeblab2.csproj b/XUnitIntegrationTestWeblab2/XUnitIntegrationTestWeblab2.csproj
index a2352e4..665815c 100644
--- a/XUnitIntegrationTestWeblab2/XUnitIntegrationTestWeblab2.csproj
+++ b/XUnitIntegrationTestWeblab2/XUnitIntegrationTestWeblab2.csproj
## -8,9 +8,14 ##
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
+ <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="3.1.1" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
<PackageReference Include="coverlet.collector" Version="1.0.1" />
</ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\weblab2\weblab2.csproj" />
+ </ItemGroup>
+
</Project>
diff --git a/weblab2/weblab2.csproj b/weblab2/weblab2.csproj
index 0fcc948..6a736ad 100644
--- a/weblab2/weblab2.csproj
+++ b/weblab2/weblab2.csproj
## -4,6 +4,10 ##
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
+ <ItemGroup>
+ <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="3.1.1" />
+ </ItemGroup>
+
</Project>

Related

How to configurate the Entity Famework Core with Azure Functions (Timer trigger) and azure sql?

I actually have a database in Azure Sql and I have an Azure function (timer trigger) in another Azure account (different from the database) I have already used Core Entity framework to map the database but when I want to do queries it doesn’t work,so there’s something wrong with the configuration.I tried a lot and tried some solutions but I still couldn’t solve this problem. I’m uploading the code hoping you can help me. Thanks in advance.
Function1.cs:
using System;
using System.Data.SqlClient;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Text;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Logging;
using Microsoft.Azure.Functions.Extensions;
using Microsoft.Net.Http;
using Microsoft.EntityFrameworkCore.SqlServer.Design;
using Microsoft.EntityFrameworkCore.SqlServer;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using Newtonsoft.Json;
namespace azuretosharepoint
{
public static class Function1
{
[FunctionName("Function1")]
public static async Task RunAsync([TimerTrigger("0 */1 * * * *")] TimerInfo myTimer, ILogger log)
{
var azsh = new ProgettokpidatabaseContext();
var listsharepoint = azsh.KpiTables.ToList();
Console.WriteLine(listsharepoint);
}
}
}
progettokpidatabaseContext.cs:
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Design;
using System.Collections.Generic;
using System.Text;
using Newtonsoft.Json;
#nullable disable
namespace azuretosharepoint
{
public partial class ProgettokpidatabaseContext : DbContext
{
public ProgettokpidatabaseContext()
{
}
public ProgettokpidatabaseContext(DbContextOptions<ProgettokpidatabaseContext> options)
: base(options)
{
}
public virtual DbSet<KpiTable> KpiTables { get; set; }
public virtual DbSet<KptKpiTarget> KptKpiTargets { get; set; }
public virtual DbSet<KpvKpiValue> KpvKpiValues { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(Environment.GetEnvironmentVariable("sqlconnectionstring"));
//#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see http://go.microsoft.com/fwlink/?LinkId=723263.
//optionsBuilder.UseSqlServer("Server=tcp:progetto-kpi.database.windows.net,1433;Initial Catalog=progetto-kpi-database;Persist Security Info=False;User ID=progetto-kpi;Password=**********;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;");
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasAnnotation("Relational:Collation", "SQL_Latin1_General_CP1_CI_AS");
modelBuilder.Entity<KpiTable>(entity =>
{
entity.HasKey(e => e.KpiId);
entity.ToTable("KPI_table");
entity.Property(e => e.KpiId)
.ValueGeneratedNever()
.HasColumnName("KPI_ID");
entity.Property(e => e.KpiBusinessArea)
.IsRequired()
.HasMaxLength(50)
.HasColumnName("KPI_Business_Area");
entity.Property(e => e.KpiDescription)
.HasMaxLength(250)
.HasColumnName("KPI_Description");
entity.Property(e => e.KpiDoi)
.HasColumnType("datetime")
.HasColumnName("KPI_DOI")
.HasDefaultValueSql("(getdate())");
entity.Property(e => e.KpiDou)
.HasColumnType("datetime")
.HasColumnName("KPI_DOU")
.HasDefaultValueSql("(getdate())");
entity.Property(e => e.KpiFrequency)
.HasMaxLength(10)
.HasColumnName("KPI_Frequency");
entity.Property(e => e.KpiManual).HasColumnName("KPI_Manual");
entity.Property(e => e.KpiName)
.IsRequired()
.HasMaxLength(50)
.HasColumnName("KPI_Name");
});
modelBuilder.Entity<KptKpiTarget>(entity =>
{
entity.HasKey(e => e.KptId)
.HasName("PK_KPT_table");
entity.ToTable("KPT_KPI_Targets");
entity.Property(e => e.KptId)
.ValueGeneratedNever()
.HasColumnName("KPT_ID");
entity.Property(e => e.KptDate)
.HasColumnType("date")
.HasColumnName("KPT_Date");
entity.Property(e => e.KptDoi)
.HasColumnType("datetime")
.HasColumnName("KPT_DOI")
.HasDefaultValueSql("(getdate())");
entity.Property(e => e.KptDou)
.HasColumnType("datetime")
.HasColumnName("KPT_DOU")
.HasDefaultValueSql("(getdate())");
entity.Property(e => e.KptKpiId).HasColumnName("KPT_KPI_ID");
entity.Property(e => e.KptTarget)
.HasColumnType("decimal(18, 2)")
.HasColumnName("KPT_Target");
entity.HasOne(d => d.KptKpi)
.WithMany(p => p.KptKpiTargets)
.HasForeignKey(d => d.KptKpiId)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("FK__KPT_KPI_T__KPT_K__2FCF1A8A");
});
modelBuilder.Entity<KpvKpiValue>(entity =>
{
entity.HasKey(e => e.KpvId)
.HasName("PK_KPV_table");
entity.ToTable("KPV_KPI_Values");
entity.Property(e => e.KpvId)
.ValueGeneratedNever()
.HasColumnName("KPV_ID");
entity.Property(e => e.KpvDate)
.HasColumnType("date")
.HasColumnName("KPV_Date");
entity.Property(e => e.KpvDoi)
.HasColumnType("datetime")
.HasColumnName("KPV_DOI")
.HasDefaultValueSql("(getdate())");
entity.Property(e => e.KpvDou)
.HasColumnType("datetime")
.HasColumnName("KPV_DOU")
.HasDefaultValueSql("(getdate())");
entity.Property(e => e.KpvKpiId).HasColumnName("KPV_KPI_ID");
entity.Property(e => e.KpvValue)
.HasColumnType("decimal(18, 2)")
.HasColumnName("KPV_Value");
entity.HasOne(d => d.KpvKpi)
.WithMany(p => p.KpvKpiValues)
.HasForeignKey(d => d.KpvKpiId)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("FK__KPV_KPI_V__KPV_K__3587F3E0");
});
OnModelCreatingPartial(modelBuilder);
}
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}
}
local.settings.json :
{
"IsEncrypted": false,
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"Values": {
"sqlconnectionstring": "Server=tcp:progetto-kpi.database.windows.net,1433;Initial Catalog=progetto-kpi-database;Persist Security Info=False;User ID=progetto-kpi;Password=*********;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;",
"ProviderName": "System.Data.SqlClient"
}
}
the problem :
Azure Functions Core Tools
Core Tools Version: 3.0.3568 Commit hash: e30a0ede85fd498199c28ad699ab2548593f759b (64-bit)
Function Runtime Version: 3.0.15828.0
Can't determine project language from files. Please use one of [--csharp, --javascript, --typescript, --java, --python, --powershell, --custom]
Missing value for AzureWebJobsStorage in local.settings.json. This is required for all triggers other than httptrigger, kafkatrigger, rabbitmqtrigger, orchestrationTrigger, activityTrigger, entityTrigger. You can run 'func azure functionapp fetch-app-settings <functionAppName>' or specify a connection string in local.settings.json.
azuretosharepoint.csproj :
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AzureFunctionsVersion>v3</AzureFunctionsVersion>
<UserSecretsId>4e8db286-9c45-4574-b556-eb0a04ac345e</UserSecretsId>
<OutputType>Library</OutputType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Dapper" Version="2.0.90" />
<PackageReference Include="Dapper.Contrib" Version="2.0.78" />
<PackageReference Include="Dapper.FluentMap" Version="2.0.0" />
<PackageReference Include="Dapper.SimpleCRUD" Version="2.3.0" />
<PackageReference Include="EntityFramework" Version="6.4.4" />
<PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.18.0-beta1" />
<PackageReference Include="Microsoft.AspNetCore.AzureKeyVault.HostingStartup" Version="2.0.4" />
<PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="5.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer.Design" Version="2.0.0-preview1-final" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="3.1.10" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.12" />
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.0-preview.4.21253.7" />
<PackageReference Include="System.Data.Common" Version="4.3.0" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.2" />
<PackageReference Include="System.IO" Version="4.3.0" />
<PackageReference Include="System.Linq" Version="4.3.0" />
<PackageReference Include="System.Runtime" Version="4.3.1" />
</ItemGroup>
<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="local.settings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
</ItemGroup>
</Project>
Your local.settings.json seems to be incorrectly formatted. Try:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"sqlconnectionstring": "YOURCONNECTIONSTRING",
"ProviderName": "IDONTUSETHISVALUE-IN-MY-CONFIGS"
}
}
Also, your connection string has the password blanked out. If you grab it from some parts of the Azure portal you'll get that. You might have done that intentionally, but if you didn't - remove the asterisks ^
A quick way to test if it is a local function configuration issue or an issue with your code:
Open new GitBash prompt / other terminal
func init TestMe --dotnet
cd TestMe
func new --name TestEndpoint --template "HTTP trigger" --authlevel "anonymous"
func start
To create a test timer trigger:
func new --name Timer --template "TIMER trigger"
The same happened to me, I had an Azure Function App working and after a some time started giving me the same exception.
My original project did not need any local.settings.json. So I created a new Azure Function Project App and copied and pasted in my old one the file local.settings.json.
Problem solved!

"CryptographicException: Invalid provider type specified" only in WebAPI project

I have the following code for accessing a secret in KeyVault using a certificate installed on the local machine:
static readonly string certThumbprint = "1234...";
static readonly string clientId = "1234...";
static void Main(string[] args)
{
X509Certificate2 certificate = FindCertificateByThumbprint(certThumbprint);
ClientAssertionCertificate assertionCert = new ClientAssertionCertificate(clientId, certificate);
var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(
(authority, resource, scope) => GetAccessToken(authority, resource, scope, assertionCert)));
string url = "https://myvault.vault.azure.net/";
var result = keyVaultClient.GetSecretAsync(url, "mySecret").Result;
}
private static X509Certificate2 FindCertificateByThumbprint(string certificateThumbprint)
{
if (certificateThumbprint == null)
{
throw new System.ArgumentNullException("CertificateThumbprint");
}
StoreLocation[] storeLocations = (StoreLocation[])Enum.GetValues(typeof(StoreLocation));
foreach (StoreLocation location in storeLocations)
{
foreach (StoreName storeName in (StoreName[])
Enum.GetValues(typeof(StoreName)))
{
X509Store store = new X509Store(storeName, location);
store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certCollection = store.Certificates.Find(X509FindType.FindByThumbprint, certificateThumbprint, false);
if (certCollection != null && certCollection.Count != 0)
{
foreach (X509Certificate2 cert in certCollection)
{
if (cert.HasPrivateKey)
{
store.Close();
return cert;
}
}
}
}
}
throw new Exception($"Could not find the certificate with thumbprint {certificateThumbprint} in any certificate store.");
}
private static async Task<string> GetAccessToken(string authority, string resource, string scope, ClientAssertionCertificate assertionCert)
{
Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext context = new Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext(authority, TokenCache.DefaultShared);
AuthenticationResult result = await context.AcquireTokenAsync(resource, assertionCert).ConfigureAwait(false);
return result.AccessToken;
}
This works fine in my .Net Framework 4.7.2 console app with the following packages installed:
<ItemGroup>
<PackageReference Include="Microsoft.Azure.KeyVault">
<Version>3.0.5</Version>
</PackageReference>
<PackageReference Include="Microsoft.IdentityModel.Clients.ActiveDirectory">
<Version>5.2.8</Version>
</PackageReference>
<PackageReference Include="System.Security.Cryptography.X509Certificates">
<Version>4.3.2</Version>
</PackageReference>
</ItemGroup>
However, when I run the exact same code on my WebAPI project (.Net Framework 4.7.2), I get the following error:
"ClassName": "System.Security.Cryptography.CryptographicException",
"Message": "Invalid provider type specified.\r\n"
The packages I've installed are the same version according to Nuget:
<Reference Include="Microsoft.Azure.KeyVault, Version=3.0.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Azure.KeyVault.3.0.5\lib\net461\Microsoft.Azure.KeyVault.dll</HintPath>
</Reference>
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory, Version=5.2.8.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.5.2.8\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.X509Certificates, Version=4.1.1.2, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Cryptography.X509Certificates.4.3.2\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
I guess that some other package is causing a conflict and resolving some incorrect version of one of the needed libraries but I'm unsure how to diagnose & resolve.
The most likely reason for this exception is that certificate's private key is stored in modern CNG Key Storage Provider rather than legacy CAPI Cryptographic Service Provider. At the moment of this response Azure Key Vault has known compatibility issues with CNG, so you should try to generate a new certificate and select legacy CAPI CSP to store key material.

read nuget.config programmatically in c#

Is it possible to read nuget.config file and packages sources inside with using Nuget.visualStudio,nuget.core or nuget.clients dll.I can parse xml but is there any outofthebox logic in nuget.dlls
Yes! You need to consume the NuGet.Configuration package available at https://www.nuget.org/packages/NuGet.Configuration/4.6.2.
Then you can use the following code -
using NuGet.Configuration;
using System;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
// basic implementation of nuget.config in code
var setting = Settings.LoadSpecificSettings(#"f:\root", "nuget.config");
// get sources
var packageSourceProvider = new PackageSourceProvider(setting);
var sources = packageSourceProvider.LoadPackageSources();
foreach(var source in sources)
{
Console.WriteLine($"{source.Name}: {source.SourceUri}");
}
}
}
}
This will generate the following output -
NuGet.org: https://api.nuget.org/v3/index.json
Sample config file used (lets say at path f:\root\nuget.config)-
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="NuGet.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>

#Before Suite and #BeforeTest methods are not called if groups are executed in TestNG

Below is my XML file and Demo Class. Precondition() method will run before demo1() method and postCondition() method will run after demo1() method. Same process is for demo2(). But when i run the code, BeforeSuite and BeforeTest Methods are not Called. Why.? How to call them ?
Output :
Before Method is executing
DEMO -1
After Method is executing
Before Method is executing
DEMO 2
After Method is executing
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite">
<test name="Test">
<groups>
<run>
<include name = "Hey"></include>
</run>
</groups>
<classes>
<class name="practicepackage.Demo"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
package practicepackage;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
public class Demo {
#BeforeSuite
public void beforeSuite(){
System.out.println("Before Suite method is being launched");
}
#BeforeTest
public void beforeTest(){
System.out.println("Before Test Method is being luanched");
}
#BeforeMethod(groups = {"Hey"})
public void PreCondition(){
System.out.println("Before Method is executing");
}
#Test (groups = {"Hey"})
public void demo1(){
System.out.println("DEMO -1 ");
}
#Test(groups = {"Hey"})
public void demo2(){
System.out.println("DEMO 2");
}
#AfterMethod(groups = {"Hey"})
public void postCondition(){
System.out.println("After Method is executing");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite">
<test name="Test">
<groups>
<run>
<include name = "Hey"></include>
</run>
</groups>
<classes>
<class name="practicepackage.Demo"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
In order to ensure that #BeforeSuite and #BeforeTest are executed all the time, please enable the attribute alwaysRun=true for these annotations.
This is required because when you run through groups, these configuration methods wont be selected by TestNG until and unless they are part of the group which you selected.
Group selection in TestNG can be visualised as a sort of filtering mechanism in TestNG that lets you tell TestNG the criteria for filtering, when it decides which tests to run.

Return value when internally calling target with phing/phingcall

I am calling a target by means of phingcall command.
I want to pass back a status variable from the called target or at least change the existing value from the calling target.
Goal: I want to branch in my main target controlling logic if the sub target fails which I indicate with a property.
The code below does not work. Any idea how to make it work or an altertive approach for my goal?
Thanks,
Juergen
<target name="main">
<echo>target a</echo>
<echo>${bOk}</echo>
<exec command="echo 1" outputProperty="bOk" />
<echo>bOk is 1: ${bOk}</echo>
<phingcall inheritRefs="true" target="sub">
</phingcall>
<echo>bOk should now be 0: ${bOk}</echo>
</target>
<target name="sub">
<echo>target b</echo>
<echo>bOk is 1: ${bOk}</echo>
<exec command="echo 0" outputProperty="bOk" />
<echo>bOk now is 0: ${bOk}</echo>
</target>
The problem here is that
<echo>bOk should now be 0: ${bOk}</echo>
echos
bOk should now be 0: 1
Even with the great help of #phing IRC I couldn't solve the problem.
I decided to write a custom task to account for data passing between targets:
<?php
require_once "phing/Task.php";
class rvGlobalTask extends Task {
private static $bOk = 1;
private $sMode = null;
private $bValue = null;
private $outputProperty = null;
public function setSMode( $sMode ) {
$this->sMode = $sMode;
}
public function setBValue( $bValue ) {
$this->bValue = $bValue;
}
public function setOutputProperty( $outputProperty ) {
$this->outputProperty = $outputProperty;
}
public function main() {
if ( $this->sMode == "set" ) {
rvGlobalTask::$bOk = $this->bValue;
} else {
$this->project->setProperty(
$this->outputProperty,
rvGlobalTask::$bOk
);
}
}
}
?>
This works fine for my problem. Perhaps someone else finds this useful as well.
Here's how you use an ExecTask to capture output.
<?xml version="1.0" encoding="UTF-8"?>
<project name="example" default="check-composer">
<!-- set a property to contain the output -->
<property name="whichComposer" value="" />
<!-- check if composer (getcomposer.org) is installed globally -->
<target name="check-composer">
<!-- put the output of "which" in our property -->
<exec command="which composer" outputProperty="whichComposer" />
<!-- act on what we found out -->
<if>
<contains string="${whichComposer}" substring="composer" />
<then>
<echo>Composer installed at ${whichComposer}</echo>
</then>
<else>
<echo message="better install composer. ${whichComposer}"/>
</else>
</if>
</target>
</project>