-
Notifications
You must be signed in to change notification settings - Fork 10
4. Testing
Unit testing is a type of software testing where individual units or components of a software are tested. The purpose is to validate that each unit of the software code performs as expected. Unit Testing is done during the development (coding phase) of an application by the developers. Unit Tests isolate a section of code and verify its correctness. A unit may be an individual function, method, procedure, module, or object.
Unit testing with Signals is implemented using the following steps:
- We define a class that extends ApplicationBootstrapConfiguration where we will define all Signals aspects that the tests will be using.
public class TestBootstrapConfiguraiton : ApplicationBootstrapConfiguration
{
}
- We implement a base fixture class that all test classes will extend.
public class BaseProcessesTest
{
/// <summary>
/// Process mediator
/// <summary>
protected Mediator Mediator => SystemBootstrapper.GetInstance<Mediator>();
/// <summary>
/// Executed when test class is initialized
/// </summary>
public BaseProcessesTest()
{
FileConfigurationProvider ProviderForFile(string name) => new FileConfigurationProvider
{
File = name,
Path = Path.Combine(AppContext.BaseDirectory, $"configs"),
ReloadOnAccess = false
};
DomainConfiguration.UseProvider(ProviderForFile("domain.config.json"));
var databaseConfig = DomainConfiguration
.Instance
.DatabaseConfiguration
.ActiveConfiguration;
TestBootstrapConfiguraiton config = new TestBootstrapConfiguraiton
{
RegistrationService = new RegistrationService(),
LoggerConfiguration = new DatabaseLoggingConfiguration
{
Database = databaseConfig.Database,
Host = databaseConfig.IpAddress,
Username = databaseConfig.Uid,
Password = databaseConfig.Pwd,
DataProvider = DataProvider.SqlClient,
TableName = "LogEntity"
},
};
var assemblies = Directory
.GetFiles(Environment.CurrentDirectory, "*.dll")
.Select(file => Assembly.LoadFrom(file)).ToArray();
config.Bootstrap(assemblies);
SystemBootstrapper.Bootstrap(this);
}
}
- We implement the unit tests in a class that extends the base class
BaseProcessesTest
.
public class UnitTests : BaseProcessesTest
{
private Mock<IMyRepository> MyRepository { get; set; }
/// <summary>
/// CTOR
/// </summary>
public UnitTests()
{
MyRepository = new Mock<IMyRepository>();
MyRepository.Setup(x => x.GetById(1)).Returns(new MyObject());
}
[Fact]
public void HavingRequest_ExecuteProcess_NotFaulted()
{
// Arrange
var request = new MyProcessRequest();
// Act
var process = Mediator.For<MyProcess>();
process.MyRepository = MyRepository.Object;
var result = process.With(request);
var response = result.Result;
// Assert
Assert.False(response.IsFaulted);
Assert.Equal(1, response.Result); // business logic assert
}
}
Integration testing is the phase in software testing in which individual software modules are combined and tested as a group. Integration testing is conducted to evaluate the compliance of a system or component with specified functional requirements. It occurs after unit testing. Integration testing takes as its input modules that have been unit tested, groups them in larger aggregates, applies tests defined in an integration test plan to those aggregates, and delivers as its output the integrated system ready for system testing.
Integration testing with Signals is implemented using the following steps:
- We define a class that extends
ApplicationBootstrapConfiguration
where we will define all Signals aspects that the tests will be using.
public class TestBootstrapConfiguraiton : ApplicationBootstrapConfiguration
{
}
- We implement a base fixture class that all test classes will extend.
public class BaseProcessesTest
{
/// <summary>
/// Web mediator
/// <summary>
private WebMediator WebMediator => SystemBootstrapper.GetInstance<WebMediator>();
/// <summary>
/// Executed when test class is initialized
/// </summary>
public BaseProcessesTest()
{
FileConfigurationProvider ProviderForFile(string name) => new FileConfigurationProvider
{
File = name,
Path = Path.Combine(AppContext.BaseDirectory, $"configs"),
ReloadOnAccess = false
};
DomainConfiguration.UseProvider(ProviderForFile("domain.config.json"));
var databaseConfig = DomainConfiguration
.Instance
.DatabaseConfiguration
.DatabaseConnections
.Single(x=>x.Name = "MyIntegrationTestDatabase");
TestBootstrapConfiguraiton config = new TestBootstrapConfiguraiton
{
RegistrationService = new RegistrationService(),
LoggerConfiguration = new DatabaseLoggingConfiguration
{
Database = databaseConfig.Database,
Host = databaseConfig.IpAddress,
Username = databaseConfig.Uid,
Password = databaseConfig.Pwd,
DataProvider = DataProvider.SqlClient,
TableName = "LogEntity"
},
};
var assemblies = Directory
.GetFiles(Environment.CurrentDirectory, "*.dll")
.Select(file => Assembly.LoadFrom(file)).ToArray();
config.Bootstrap(assemblies);
SystemBootstrapper.Bootstrap(this);
}
/// <summary>
/// Mock and send web request to api process
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="path"></param>
/// <param name="method"></param>
/// <param name="queryString"></param>
/// <param name="body"></param>
/// <returns></returns>
protected T MockRequest<T>(string path, ApiProcessMethod method, string queryString = null, object body = null)
where T : VoidResult
{
// build http context
var context = new DefaultHttpContext();
context.Response.Body = new MemoryStream();
context.Request.Path = path;
context.Request.Method = method.ToString();
if (!queryString.IsNullOrEmpty())
context.Request.QueryString = QueryString.FromUriComponent(queryString);
if (!body.IsNull())
context.Request.Body = new MemoryStream(Encoding.Default.GetBytes(body.SerializeJson()));
// mock context accessor
var mockHttpContextAccessor = new Mock<IHttpContextAccessor>();
mockHttpContextAccessor.Setup(_ => _.HttpContext).Returns(context);
var request = new HttpContextWrapper(mockHttpContextAccessor.Object);
// dispatch mock web request
WebMediator.Dispatch(request);
// read response
context.Response.Body.Position = 0;
return new StreamReader(context.Response.Body).ReadToEnd().Deserialize<T>();
}
}
- We implement the integration tests in a class that extends the base class
BaseProcessesTest
.
public class IntegrationTests : BaseProcessesTest
{
[Fact]
public void HavingRequest_ExecuteProcess_NotFaulted()
{
// Arrange
var path = "/api/MyApiProcess";
var method = ApiProcessMethod.POST;
var queryString = "?MyProperty=MyValue";
var body = new MyRequestBody
{
MyProperty = "MyValue"
};
// Act
var response = MockRequest<MethodResult<int>>(path, method, queryString, body);
// Asset
Assert.False(response.IsFaulted);
Assert.Equal(1, response.Result); // business logic assert
}
}