I have an interface IVehicle
public interface IVehicle
{
Task<ApiResponse> GetVehicleInfo();
}
This is my implementation of the interface
public class Vehicle : IVehicle
{
private string m_vehicleId;
private VehicleInfoEndPoint m_vEndPoint;
public Vehicle()
{
}
public Vehicle(string vehicleId, string device, HttpClient client,string Uri)
{
m_vEndPoint = new VehicleInfoEndPoint(device, client, Uri);
}
public async Task<ApiResponse> GetVehicleInfo()
{
await m_vEndPoint.GetVehicleInfoPostAsync();
return m_vehicleInfoEndPoint.FullResponse;
}
}
I want to unit test this class. For that I have written the following code.
[Test]
public void Vehicle_GetVehicleInformation_shouldCall_VehicleInfoEndPoint_GetVehicleInfo()
{
var endPointMock = Mock.Of<IVehicleInfoEndPoint>();
var result = new ApiResponse();
var vehicle = new Mock<IVehicle>();
vehicle.Setup(x => x.GetVehicleInfo()).Returns(Task.FromResult(result));
var response = vehicle.Object.GetVehicleInfo().Result;
Mock.Get(endPointMock).Verify(x => x.GetVehicleInfo(), Times.Once);
}
My test is failing with the error that
Expected invocation on the mock once, but was 0 times x=> x.GetVehicleInfo()
In this case, it seems you want to test is that x.GetVehicleInfoPostAsync() is called.
Being this the case, you have to define your unit artifacts which are:
Vehicle is your system under test
IVehicleInfoEndPoint is your mock
You want to assert that calling GetVehicleInfo() calls the mock endpoint
I made this quick example that does what you want:
class Program
{
static async Task Main(string[] args)
{
// ARRANGE
var endPointMock = Mock.Of<IVehicleInfoEndPoint>();
var vehicle = new Vehicle(endPointMock);
// ACT
var response = await vehicle.GetVehicleInfo();
// ASSERT
Mock.Get(endPointMock).Verify(x => x.GetVehicleInfoPostAsync(), Times.Once);
}
}
public interface IVehicle
{
Task<ApiResponse> GetVehicleInfo();
}
public class Vehicle : IVehicle
{
private readonly IVehicleInfoEndPoint _endpoint;
public Vehicle(IVehicleInfoEndPoint endpoint)
{
_endpoint = endpoint ?? throw new ArgumentNullException(nameof(endpoint));
}
public async Task<ApiResponse> GetVehicleInfo()
{
await _endpoint.GetVehicleInfoPostAsync();
return _endpoint.FullResponse;
}
}
public interface IVehicleInfoEndPoint
{
Task GetVehicleInfoPostAsync();
ApiResponse FullResponse { get; set; }
}
public class ApiResponse
{
}
It helps when you divide your test into 3 parts:
Arrange
Act
Assert
Check this out: What is a "Stub"?
Also, checkout "The art of unit testing" on Amazon, great book.
Related
I have a function which contains validation that check whether a variable value is null or not. I want to test that class method using xunit test. But due to this validation, I failed to call the Unit Test.
Class
public interface ICountry<CountryModel>
{
Task ProcessCall(IList<string> countryCodes);
}
public class CallOptions
{
public string Name { get; set; }
}
public class Country<CountryModel> : ICountry<CountryModel>
{
private readonly CallOptions _options;
private readonly Irepo _repo;
public Country(IOptions<CountryModel> options,Irepo repo)
{ _repo= repo
_options = options.Value;
if (string.IsNullOrWhiteSpace(_options.Name))
{
throw new ArgumentException("Missing name");
}
}
public async Task ProcessCall(IList<string> Codes)
{
_repo.set(Codes);
}
Unit Test
public class ProcessorTests
{
private Mock<Irepo> _RepositoryMock;
private Mock<IOptions<CallOptions>> options;
public ProcessorTests()
{
_RepositoryMock = new Mock<Irepo>();
options = new Mock<IOptions<CallOptions>>();
options.SetReturnsDefault("test");
}
private Country<CountryModel> CreateSut()
{
return new Country<CountryModel>(_RepositoryMock.Object, _options.Object);
}
[Fact]
public async Task ShouldCheck()
{
GetRepoMock();
await CreateSut().ProcessCall(new string[] { "TEST" });
_RepositoryMock.Verify(x => x.set(It.IsAny<List<string>>()), Times.Once);
}
private void GetRepoMock()
{
_RepositoryMock
.Setup(m => m.set(It.IsAny<List<string>>())
.ReturnsAsync(new Response<Code>(false, null, Enumerable.Empty<Code>()));
}
But when the unit test executes, the value of _options.Name is empty and failed the test while called the Country method.
Any idea regarding this?
I am using xunit to do integration testing, and below is my test class.
public class CodesAndGuidelinesTest : IClassFixture<SchemaCache>
{
public readonly SchemaCache schemaCache;
public CodesAndGuidelinesTest(PostgreSqlResource resource)
{
schemaCache = new SchemaCache(resource);
}
[Fact]
public async Task Create_Name_Contains_Expression()
{
IRequestExecutor requestExecutor = await schemaCache.CodesAndGuidelinesExecutor;
.......
}
}
Here is the schema cache class
public class SchemaCache : QueryTestBase
{
Task<IRequestExecutor> _codesAndGuidelinesExecutor;
public SchemaCache(PostgreSqlResource resource) : base(resource)
{
_codesAndGuidelinesExecutor = CreateDb(CodesAndGuidelinesMockFixture.codeStandardGuidelines);
}
public Task<IRequestExecutor> CodesAndGuidelinesExecutor
{
get { return _codesAndGuidelinesExecutor; }
}
}
Here CodesAndGuidelinesMockFixture.codeStandardGuidelines is just a mock object, and When I run the test cases, I am getting the below error.
Class fixture type 'API.Tests.SchemaCache` had one or more unresolved
constructor arguments: PostgreSqlResource resource,
CodeStandardGuideline[] codesAndGuidelines The following
constructor parameters did not have matching fixture data:
PostgreSqlResource resource
I am not sure where I am doing wrong with the above code. Could anyone point me in the right direction?
Thanks!!!
Update :
QueryTestBase class
public class QueryTestBase
{
private readonly PostgreSqlResource _resource;
public QueryTestBase(PostgreSqlResource resource)
{
_resource = resource;
}
protected async Task<Func<IResolverContext, IQueryable<T>>> BuildResolverAsync<T>(T[] arrayOfEntities) where T : class
{
var databaseName = Guid.NewGuid().ToString("N");
var options = new DbContextOptionsBuilder<APIDbContext>()
.UseNpgsql(_resource.ConnectionString)
.Options;
.......
.......
return _ => set.AsQueryable();
}
protected async Task<IRequestExecutor> CreateDb<T>(T[] Entities) where T : class
{
Func<IResolverContext, IQueryable<T>> resolver = await BuildResolverAsync(Entities);
return .......
}
}
Your tool (Squadron) provides an easy way to have a PostgreSqlResource.
This resource has this properties:
implement standard IDisposable interface (or xunit speficIAsyncLifetime interface)
has a parameterless contructor
// sync implementation
class PostgreSqlResource : IDisposable
{
public PostgreSqlResource()
{
// init code
}
// props and logic
public Dispose()
{
// dispose code
}
}
// async implementation
class PostgreSqlResource : IAsyncLifetime
{
public PostgreSqlResource()
{
}
public async Task InitializeAsync()
{
// init code
}
// props and logic
public async Task DisposeAsync()
{
// dispose code
}
}
This object can be shared in xunit in 3 way:
for each test: create fixture, execute test, dispose fixture
for each class: create fixture, execute tests inside a class, dispose fixture
for a set of classes: create fixture, execute marked test classes, dispose fixture
In your case you need the 3rd way.
So Squadron provide a fixture for you, jou just need to define a TestCollection to mark your classes.
[CollectionDefinition("Squadron")]
public class DatabaseCollection : ICollectionFixture<PostgreSqlResource>
{
// This class has no code, and is never created. Its purpose is simply
// to be the place to apply [CollectionDefinition] and all the
// ICollectionFixture<> interfaces.
}
and after that you can simply tag your test classes with attribute [Collection("Squadron")] that allow you in inject via constructor the shared instance.
[Collection("Squadron")]
public class DatabaseTestClass1
{
PostgreSqlResource fixture;
public DatabaseTestClass1(PostgreSqlResource fixture)
{
this.fixture = fixture;
}
}
[Collection("Squadron")]
public class DatabaseTestClass2
{
// ...
In case PostgreSqlResource is not enought and you need a more complex fixture is very easy; you can just create your own fixture around the other.
Of course you need to implement the same interface and delegate implementation to inner member.
class ComplexFixture: IAsyncLifetime
{
private PostgreSqlResource _pg;
public ComplexFixture()
{
_pg = new PostgreSqlResource();
}
// fixture methods
public async Task InitializeAsync()
{
await _pg.InitializeAsync();
}
public async Task DisposeAsync()
{
await _pg.DisposeAsync();
}
}
And refer to ComplexFixture insted of PostgreSqlResource on xunit CollectionFixtures. This approach is not suggested.
In my opinion is better a Plain fixture injected to test class, and than wrapped in a class fixture object if needed.
[Collection("Squadron")]
public class DatabaseTestClass1 : IDisposable
{
// each test lifecycle
private MyComplexFixture _fixture;
// global lifecycle
public DatabaseTestClass1(DatabaseFixture dbFixture)
{
_fixture = new MyComplexFixture(dbFixture)
}
// tests
public Dispose()
{
// this can reset db state for a new test
_fixture.Dispose();
}
}
public class MyComplexFixture : IDisposable
{
public MyComplexFixture (DatabaseFixture dbFixture)
{
// ...
}
public Dispose()
{
// reset logic like DROP TABLE EXECUTION
// Please note that dbFixture shoul no be disposed here!
// xunit will dispose class after all executions.
}
}
So applying this solution to your code can be as follows.
[CollectionDefinition("SquadronSchemaCache")]
public class DatabaseCollection : ICollectionFixture<SchemaCache>
{
}
[Collection("SquadronSchemaCache")]
public class CodesAndGuidelinesTest
{
public readonly SchemaCache schemaCache;
public CodesAndGuidelinesTest(SchemaCache resource)
{
this.schemaCache = schemaCache;
}
[Fact]
public async Task Create_Name_Contains_Expression()
{
IRequestExecutor requestExecutor = await schemaCache.CodesAndGuidelinesExecutor;
.......
}
}
public class SchemaCache : QueryTestBase
{
Task<IRequestExecutor> _codesAndGuidelinesExecutor;
public SchemaCache() : base(new PostgreSqlResource())
{
_codesAndGuidelinesExecutor = CreateDb(CodesAndGuidelinesMockFixture.codeStandardGuidelines);
}
public Task<IRequestExecutor> CodesAndGuidelinesExecutor
{
get { return _codesAndGuidelinesExecutor; }
}
}
public class QueryTestBase : IAsyncLifetime
{
private readonly PostgreSqlResource _resource;
public QueryTestBase(PostgreSqlResource resource)
{
_resource = resource;
}
protected async Task<Func<IResolverContext, IQueryable<T>>> BuildResolverAsync<T>(T[] arrayOfEntities) where T : class
{
var databaseName = Guid.NewGuid().ToString("N");
var options = new DbContextOptionsBuilder<APIDbContext>()
.UseNpgsql(_resource.ConnectionString)
.Options;
.......
.......
return _ => set.AsQueryable();
}
protected async Task<IRequestExecutor> CreateDb<T>(T[] Entities) where T : class
{
Func<IResolverContext, IQueryable<T>> resolver = await BuildResolverAsync(Entities);
return .......
}
public async Task InitializeAsync()
{
await _resource.InitializeAsync();
}
public async Task DisposeAsync()
{
_resource.Dispose()
}
}
I have a question, I have a dependency that is resolved using the Func delegate, how can I use moq in this scenario?
public Func<string, IMylogic> MyLogic { get; set; }
The definition is this:
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddTransient(Factory);
}
private static Func<IServiceProvider, Func<string, IMyLogic>> Factory =>
service =>
{
return key =>
{
return new MyLogic(key, new System.Net.Http.HttpClient());
};
};
}
This is just an idea on how the test should work:
public class ExecuteEmitLogicTest
{
ExecuteTransactionCommand ExecuteEmitCommand;
Dictionary<string, StringValues> queryString;
Mock<Func<string, IMyLogic>> Concrete;
[Fact]
public async Task ExecuteEmit()
{
var Concrete = mockFactory.Create<Func<string, IMyLogic>>(MockBehavior.Loose);
Concrete.Setup(c => c.Invoke(ConcreteTInfo).Execute(request, Guid.Parse(sessionId))).Returns(Task.FromResult(pol));
ExecuteEmitCommand = new ExecuteTransactionCommand(Concrete.Object);
var response = await ExecuteEmitCommand.ExecuteAndEmit(queryString, ConcreteTInfo.ApiSkrUrl, ConcreteTInfo.SkrKey, FIXED_HASH);
Assert.True(response.IsValid);
}
}
I don't understand the redirection part with the <string, interface> function, but I would imagine the test to look more like this:
public interface IMyLogic { int GetX(); }
...
Mock<IMyLogic> mockLogic = new Mock<IMyLogic>(MockBehavior.Strict);
// For the unit test always return the mock as
// we are *not* testing the IMyLogic provider function
Func<string, IMyLogic> f = (string _) => mockLogic.Object;
mockLogic.Setup(ml => ml.GetX()).Returns(7);
var tested = new ExecuteTransactionCommand(f);
var response = await tested.ExecuteAndEmit(queryString, ConcreteTInfo.ApiSkrUrl, ConcreteTInfo.SkrKey, FIXED_HASH);
// Asserts here
This is the class contains EnqueueJobAsync method which I want to write test for it :
public class ConsumerBaseForTesting
{
protected IJobStore JobStore { get; private set; }
public ConsumerBaseForTesting(IJobStore jobStore)
{
JobStore = jobStore;
}
public async Task<IJob> EnqueueJobAsync(IJob job)
=> await JobStore.CreateAsync(job);
}
This is my test which Fails and its actual return is always NULL !
public class ConsumerBaseTest
{
private readonly Mock<IJobStore> _moqIJobStore;
private readonly ConsumerBaseForTesting _consumerBase;
public ConsumerBaseTest()
{
_moqIJobStore = new Mock<IJobStore>();
_consumerBase = new ConsumerBaseForTesting(_moqIJobStore.Object);
}
[Theory]
[ClassData(typeof(JobClassForTesting))]
public async Task EnqueueJobAsyncTest(IJob job)
{
var jobResult = await _consumerBase.EnqueueJobAsync(job);
Assert.Equal(job, jobResult);
}
}
The mock needs to be setup to do two things in order to replicate the expected behavior.
It needs to return the passed job in a completed task.
//...
public ConsumerBaseTest() {
_moqIJobStore = new Mock<IJobStore>();
_consumerBase = new ConsumerBaseForTesting(_moqIJobStore.Object);
//setup the mock to capture and return the job when CreateAsync(IJob job) is invoked
_moqIJobStore
.Setup(_ => _.CreateAsync(It.IsAny<IJob>()))
.Returns((IJob x) => Task.FromResult(x)); }
//...
.Returns((IJob x) => Task.FromResult(x)) captures the argument and returns completed Task<IJob>
I am having a simple controller which needs to be unit tested not integration tested. I just need a way to mock so that I can verify if receive method is called. We already have test against Receive(), so no need to verify what is going inside that method.
My code looks like
public class MessageController : Controller
{
private readonly ConnectionDetail connectionDetail;
private readonly QueueDetail queueDetail;
public MessageController(IOptions<ConnectionDetail> connectionDetail, IOptions<QueueDetail> queueDetail)
{
this.connectionDetail = connectionDetail.Value;
this.queueDetail = queueDetail.Value;
}
[HttpGet()]
public IActionResult Get()
{
try
{
var channel = CreateConnectionAndChannel(queueDetail);
var message = channel.Receive();
var hbaseKey = new HbaseKey { Key = new Guid(message) };
return Ok(hbaseKey);
}
catch
{
return StatusCode(500, "Exception occured while processing. Try again.");
}
}
private IChannel CreateConnectionAndChannel(QueueDetail queueDetail)
{
var factory = new Factory();
var adapter = factory.Connect(MessagingType.MQ, connectionDetail);
return adapter.BindQueue(queueDetail);
}
}
Refactor the CreateConnectionAndChannel function out into its own service
public interface IChannelProvider {
IChannel CreateConnectionAndChannel();
}
and have controller explicitly depend on that service
public class MessageController : Controller {
private readonly IChannelProvider channelProvider;
public MessageController(IChannelProvider channelProvider) {
this.channelProvider = channelProvider;
}
[HttpGet()]
public IActionResult Get() {
try {
var channel = channelProvider.CreateConnectionAndChannel();
var message = channel.Receive();
var hbaseKey = new HbaseKey { Key = new Guid(message) };
return Ok(hbaseKey);
} catch {
return StatusCode(500, "Exception occured while processing. Try again.");
}
}
}
So now only the IChannelProvider needs to be mocked to test the controller in isolation.
I just need a way to mock so that I can verify if receive method is called.
public void Verify_Received_Called() {
//Arrange
var channel = new Mock<IChannel>();
channel
.Setup(_ => _.Receive())
.Returns("My mock value here");
var mockProvider = new Mock<IChannelProvider>();
mockProvider.Setup(_ => _.CreateConnectionAndChannel())
.Returns(channel.Object);
var controller = new MessageController(mockProvider.Object);
//Act
var result = controller.Get();
//Assert
channel.Verify(_ => _.Receive(), Times.AtLeastOnce);
}
The provider implementation could look like...
public class ChannelProvider : IChannelProvider {
private readonly ConnectionDetail connectionDetail;
private readonly QueueDetail queueDetail;
public ChannelProvider(IOptions<ConnectionDetail> connectionDetail, IOptions<QueueDetail> queueDetail) {
this.connectionDetail = connectionDetail.Value;
this.queueDetail = queueDetail.Value;
}
public IChannel CreateConnectionAndChannel() {
var factory = new Factory();
var adapter = factory.Connect(MessagingType.MQ, connectionDetail);
return adapter.BindQueue(queueDetail);
}
}
In order to do this, you need to move your CreateConnectionAndChannel method to a separate dependency, for instance, ChannelFactory which implements IChannelFactory interface.
public interface IChannelFactory {
IChannel CreateConnectionAndChannel(QueueDetail queueDetail);
}
public class ChannelFactory : IChannelFactory {
public IChannel CreateConnectionAndChannel(QueueDetail queueDetail)
{
var factory = new Factory();
var adapter = factory.Connect(MessagingType.MQ, connectionDetail);
return adapter.BindQueue(queueDetail);
}
}
public class MessageController : Controller
{
private readonly ConnectionDetail connectionDetail;
private readonly QueueDetail queueDetail;
private readonly IChannelFactory channelFactory;
public MessageController(IOptions<ConnectionDetail> connectionDetail, IOptions<QueueDetail> queueDetail, IChannelFactory channelFactory)
{
this.connectionDetail = connectionDetail.Value;
this.queueDetail = queueDetail.Value;
this.channelFactory = channelFactory;
}
[HttpGet()]
public IActionResult Get()
{
try
{
var channel = channelFactory.CreateConnectionAndChannel(queueDetail);
var message = channel.Receive();
var hbaseKey = new HbaseKey { Key = new Guid(message) };
return Ok(hbaseKey);
}
catch
{
return StatusCode(500, "Exception occured while processing. Try again.");
}
}
}
After that you can mock your controller in test (using Moq for example):
[TestFixture]
public class TestMessageController
{
[Test]
public void TestGet()
{
var channelMock = new Mock<IChannel>(MockBehavior.Strict);
channelMock
.Setup(c => c.Receive())
.Returns(null);
var channelFactoryMock = new Mock<IChannelFactory>(MockBehavior.Strict);
channelFactory
.Setup(cf => cf.CreateConnectionAndChannel(It.IsAny<IOptions<QueueDetail>>()))
.Returns();
var controller = new MessageController(null, null, channelFactoryMock.Object);
controller.Get();
}
}