Posts Tagged - testing

Moq (It.isAny & mock multiple calls)

Mocking examples with Moq

It.IsAny<T> variables

Those are argument matchers we have in Moq for the case we don’t have the same instance match.

Exact instance match - most restrictive

Example for default comparison

[Theory, Autodata]
public async Task FilledString_Execute_CorrectlyProcessed(string name, AnimalDTO animal)
{
	// ARRANGE
	_dependencyMock
		.Setup(m => m.Load(name))
		.Returns(animal)
	
	// ACT
	AnimalDTO result = await _sut.Execute(name);
	
	// ASSERT
	_dependencyMock.Verify(m => m.Load(name));
}

It.IsAny<T> - most permissive

Matches any instance of that type, null included.

[Theory, Autodata]
public async Task FilledString_Execute_CorrectlyProcessed(string name, AnimalDTO animal)
{
	// ARRANGE
	_dependencyMock
		.Setup(m => m.Load(name))
		.Returns(animal)
	
	// ACT
	AnimalDTO result = await _sut.Execute(name);
	
	// ASSERT	
	// we use this in case the property is not accesible
	//   for example: a param created inside the class
	_dependencyMock.Verify(m => m.Load(It.IsAny<string>()));
}

It.Is<T>(predicate)

Matches only when the predicate is true.

[Theory, Autodata]
public async Task FilledString_Execute_CorrectlyProcessed(string name, AnimalDTO animal)
{
	// ARRANGE
	_dependencyMock
		.Setup(m => m.Load(name))
		.Returns(animal)
	
	// ACT
	AnimalDTO result = await _sut.Execute(name);
	
	// ASSERT
	_dependencyMock.Verify(m => m.Load(It.Is<AnimalDTO>(a => a.Name == name)));
}

It.IsNotNull<T>

Only checks something is not null

[Theory, Autodata]
public async Task FilledString_Execute_CorrectlyProcessed(string name, AnimalDTO animal)
{
	// ARRANGE
	_dependencyMock
		.Setup(m => m.Load(name))
		.Returns(animal)
	
	// ACT
	AnimalDTO result = await _sut.Execute(name);
	
	// ASSERT
	_dependencyMock.Verify(m => m.Load(It.IsNotNull<AnimalDTO>()));
}

Mock multiple calls with same params

This is an example on how to mock a call when it’s called multiple times, and with the same parameter type every time.

Setup

I have the following class…

public class ConnectorRequest
{
	public string Query { get; set; }
}

… which will be consumed by the following service

public class IConnectorService
{
	Task<string> Execute(ConnectorRequest request);
}

Then I have a class which calls IConnectorService multiple times

public class ConnectorConsumerService
{
	private IConnectorService _service;
	
	// ...
	
	public async Task<string> Process() 
	{
		// ... does whatever
		var response1 = await _service.Execute(request1);
		// ... does whatever with that information
		var response2 = await _service.Execute(request2);
		// ... does whatever with that information
		var response3 = await _service.Execute(request3);
		// ... does whatever with that information
		// ... does whatever else
	}
	
	// ...
	
}

Test

Test which mocks multiple calls

public class ConnectorConsumerServiceTest
{
	// all mocks and stubs
	private Mock<IConnectorService> _dependencyMock;

	// service under test
	private ConnectorConsumerService _service;

	public ConnectorConsumerServiceTest()
	{
		_dependencyMock = new Mock<IConnectorService>();
		_service = new ConnectorConsumerService(_dependencyMock.Object);
	}

	[Fact]
	public async Task ProcessXXX_CaseXXX_ShouldReturnOkay()
	{
		// ARRANGE
		// example starts here! -> 
		var responseToExecution1 = new ConnectorRequest
		{
			Query = "some response";
		}
		var responseToExecution2 = new ConnectorRequest
		{
			Query = "another response";
		}
		var responseToExecution3 = new ConnectorRequest
		{
			Query = "oh no! a response";
		}
		
		_dependencyMock.SetupSequence(mock => mock.Execute(It.IsAny<ConnectorRequest>()))
			.ReturnsAsync(responseToExecution1)
			.ReturnsAsync(responseToExecution2)
			.ReturnsAsync(responseToExecution3);
		// <- example ends here

		// ACT
		var result = await _service.Process();
	
		// ASSERT
		result.status.Should().NotBeNull();
		// ... assert whatever
	}
}

Read More

Fluent Assertions examples

Examples on how to test and assert exceptions with FluentAssertions.

with * it checks it contains the string. if you want exact matching, remove them

[Fact]
public async Task CreateAnimal_IsNull_ExceptionThrown()
{
	// ARRANGE 
	Animal? animal = null;
	
	// ACT 
	var act = async () => await sut.Create(animal);
	
	// ASSERT
	await act.Should().ThrowAsync<ArgumentNullException>()
		.WithMessage("*is null*");
}

Read More

AutoFixture (AutoData & AutoMoq)

AutoFixture is a .NET library to automatically generate test data. To use it install the following packages

AutoFixture
AutoFixture.Xunit2
AutoFixture.AutoMoq

Inyecting with AutoData

You can create the fixtures either manually or automatically. I do it automatically with [AutoData]

test class

public class AnimalControllerTests
{
	private readonly Mock<AnimalService> _serviceMock;
	private readonly AnimalController _sut;
	
	public AnimalControllerTests()
	{
		_serviceMock = new Mock<AnimalService>();
		_sut = new AnimalController(_serviceMock.Object);
	}
}

test method example

[Theory, AutoData]
public async Task Animal_Process_IsCorrectlyCreated(Animal animal, Guid guid)
{
	// when calling this test, Animal and Guid have already been inyected
	
	// ARRANGE
	_serviceMock.Setup(x => x.Create(animal))
		.Returns(guid);
	
	// ACT
	var resultGuid = await _sut.Process(animal);
	
	// ASSERT
	_serviceMock.Verify(m => m.Create(animal));
	resultGuid.Should().Be(guid);
}

Read More

XUnit tags and usage

Fact vs Theory

[Fact] son tests que se ejecutan siempre con los mismos valores fijos

[Fact]
public void Sum_TwoNumbers_ReturnsCorrectResult()
{
	// Act
	var result = 1 + 2;
	
	// Assert
	result.Should().Be(3);
}

[Theory] son tests parametrizados que se ejecutan múltiples veces con datos diferentes. Requieren de otro modificador que provea los valores

[Theory]
[InlineData(1, 2, 3)]
[InlineData(0, 0, 0)]
[InlineData(-1, 1, 0)]
public void Sum_TwoNumbers_ReturnsCorrectResult(int a, int b, int expected)
{
	// Act
	var result = a + b;
	
	// Assert
	result.Should().Be(expected);
}

Read More

Testing. Code example for c# (NUnit)

(this project contains examples on how to use NUnit. Nowadays it’s better to use XUnit for new projects).

The following are code examples to test several scenarios.

(check this project to see more testing code examples)

General tests

This is a test to check an exception is thrown for a non-async method.

The method .WithMessage("*null payload*") works as a like. Any string that contains null payload will trigger as true.

[Test]
public async Task GivenNullPayload_WhenSetupPost_ThenAssertExceptionIsThrown
{
	// given
	string url = "http://somethingsomething.com"
	string nullPayload = null;
	
	// when
	Action result = () => _service.SetUpPost(url, nullPayload);
	
	// then
	result.Should().Throw<ArgumentNullException>().WithMessage("*null payload*");
}

This is the example for an async method.

[Test]
public async Task GivenNullPayload_WhenSetupPostAsync_ThenAssertExceptionIsThrown
{
	// given
	string url = "http://somethingsomething.com";
	string nullPayload = null;
	
	// when
	Func<Task> result = () => _service.SetUpPostAsync(url, nullPayload);
	
	// then
	await result.Should().ThrowAsync<InvalidOperationException>().WithMessage("*null payload*");
}

Read More

XUnit test examples

Controller test example

this includes how to mock a request’s header - but it’s a bogus test. this only shows how to use XUnit and its structure.

public class XXXControllerTest
{
	// all mocks and stubs
	private Mock<IXXXService> _serviceMock;
	
	// controller under test 
	private XXXController _controller;
	
	public XXXControllerTest() 
	{
		_serviceMock = new Mock<IXXXService>();
		_controller = new XXXController(_serviceMock.Object);
	}
	
	[Fact]
	public async Task CallXXX_ShouldCall_Service()
	{
	// ARRANGE
	
	// mock header
	var httpContext = new DefaultHttpContext();
	httpContext.Request.Headers["someHeader"] = "my-mocked-value";
	_controller.ControllerContext = new ControllerContext
	{
		HttpContext = httpContext
	};
	
	// mock request
	string mockedValue = "someInputValueTo_serviceMock";
	string mockedResponse = "someResponseValueFrom_serviceMock";
	_serviceMock.Setup(mock => mock.SomeMethodCall(mockedValue)).ReturnsAsync(mockedResponse);
	
	// ACT
	var response = await _controller.CallSomething(mockedValue) as OkObjectResult;
	
	// ASSERT
	response.Should().NotBeNull();
	response.StatusCode.Should().Be(200);
	response.Value.Should().BeEquivalentTo(mockedResponse);
	}
}

Basic service test example

public class XXXServiceTest
{
	// all mocks and stubs
	private Mock<IXXXDependency> _dependency;

	// service under test
	private XXXService _serviceMock;

	public XXXServiceTest()
	{
		_dependency = new Mock<IXXXDependency>();
		_serviceMock = new XXXService(_dependency.Object);
	}

	[Fact]
	public async Task ProcessXXX_CaseXXX_ShouldReturnOkay()
	{
		// ARRANGE
		string paramX = "something";
		string responseX = "some response";
		_serviceMock.Setup(mock => mock.SomeMethodCall(paramX)).ReturnsAsync(responseX);
		
		// ACT
		var result = await _service.ProcessXXX(paramX);
	
		// ASSERT
		result.status.Should().NotBeNull();
		// ... assert whatever
	}
}

Read More

Windows debug errores

Visor de eventos

Aqui se pueden ver logs de errores y warnings. Interesantes son las carpetas de Registros de Windows - Aplicacion y Sistema

Administrador de dispositivos

Si hay fallos de red aqui se puede ver el estado de los Adaptadores de Red:

Read More

Test APIs with Postman - Scripting

We can set pre-request scripts (run before the request) & tests (after execution) at several levels:

  • Collection
  • Folder
  • Request

Snippets

Inside pre-request Script and Tests we have a SNIPPETS column with templates we may use for our code.

Get / Set variables

console.log("Hello world");

// work with local vars
let urlVar = pm.variables.get("protocol");
console.log("value for protocol: " + urlVar);

pm.variables.set("protocol", "http");
console.log(pm.variables.get("protocol"));  

// work with global vars
let globalVar = pm.globals.get("env");
console.log(globalVar);

Read More

Test APIs with Postman - GUI

To test postman I use https://reqres.in. You can use it to learn how to write Postman tests.

Collections

Collections have metadata which you can set up. This includes:

  • Authorization so you don’t need to set it for every single request.
  • Variables, for variables only for this collection (so you don’t use environment vars).
  • Collection tests.

Read More

JMeter performance testing

We’re going to use a test app. Supposedly, this app has passed a first development iteration, and has passed unit and functional testing. With JMeter we measure its performance.
Performance testing should start early and continue through the whole dev process.

JMeter is not a browser. It doesn’t execute JavaScript!

Performance Testing

Performance is related to how fast an app executes an operation. Performance testing is about how an app or resource performs under a given load, to see its impact. It should be done after the app has passed all functional tests and we’re sure it works correctly.

Performance testing is measured in terms of:

  • response time: request time + processing time + network latency.
  • throughput: number of transactions (request/response) / unit of time (ms / seconds).
  • reliability: how well the app detects and handles errors. number of errors / number of requests.
  • scalability: tells how well the system expands its capacity in terms of response time, throughput and reliability when additional resources are added.

    • vertical scalability: adding more memory or additional CPUs.
    • horizontal scalability: adding servers to a cluster.

Performance requirements

They’re are usually set up in contracts, such as:

  • average / maximum response time.
  • pages per second the system should be able to support.
  • users per hour the system should be able to support.

Process to follow

  • Design and build tests: We have to know the app and its usage patterns.
  • Prepare test environment: configure a test env similar to prod.
  • Run the test: validate the script and test data. Monitor server logs!
  • Analyze the results
  • Optimize
  • Retest

Types of Performance Tests

  • Increase the number of users.
  • Increase the number of requests.

Almost always you should execute a smoke test first. This is a test with light load to verify the test works correctly.

A load test is a test that’s performed at a specific load level. Usually you’ll perform them at many load levels to monitor the app’s behavior.

A stress test tests the app with loads past its normal working range, to see up to which point it stays stable and responsive.

At a spike test the app is subjected to brief periods of sudden increments in the load beyond its maximum capacity, to see if the app is robust enough to work during and after the spike.

Endurance tests, where the app is subjected to load within its limits for a long duration (hours or even days) to search for memory leaks.

Read More

JMeter

JMeter is a testing tool to simulate thousands of users. It uses Java Threads for this.

Configure a Test Plan

In JMeter the components of a test are organized in a tree, where each component has a scope that determines to what other components it has access to.

Test Plan

Test Plan is the root element of a test, where all overall settings are specified and all the other elements are contained.

It allows us to:

  • Define variables to the entire test.
  • There we can set to run Thread Groups consecutively, instead of parallel.
  • We may run tearDown Thread Groups. They run at the end of the test, after a graceful shutdown of the main Threads. They won’t be run if the test is forcibly stopped.
  • If we select Functional Test Mode, JMeter will save information from the server responses to result files. Beware, as this files grow quickly and they impact performance. Only for small tests.
  • We may add jar files or directories to classpath, so they will load just for the test script.

Thread Groups

They’re the entry point of a test and controls the number of threads (users) JMeter will use to execute a test. We also have setUp and tearDown Thread Groups.

We may:

  • Set the number of users and the time it will take to create them. This creation can be delayed until they’re needed.

Configuration Elements

They’re used to set up default configurations and variables for later use by other components. They can be placed under any other component.

They are classified into:

  • elements that allows us to set variables: CSV Data Set Config, Counter or Random Variable.
  • elements that allows us to define a Configuration: JDBC Connection Configuration, KeyStore Configuration, Login Config Element.
  • managers that allow us to manage configuration params: HTTP Header Manager, HTTP Cookie Manager, HTTP Cache Manager.
  • default configuration elements: HTTP Request Defaults, FTP Request Defaults, Java Request Defaults.

The most common used are:

  • CSV Data Set Config used to read the content of a CSV file and turn it into variables.
  • HTTP Header Manager allows us to add or override HTTP Request Headers.
  • HTTP Cookie Manager For each user, it stores and sends a cookie like a browser; Allows to manually add a cookie that will be shared by all users.
  • HTTP Cache Manager Adds caching functionality to HTTP Request. Each user has its own cache.
  • User defined variables allows you to define a set of variables. They’re processed once at the start of the test and are shared between old thread groups.

He created an HTTP Request Defaults and added the IP and port number, so he doesn’t need to repeate this at every component.

Read More