How to set a Moq value in Constructor C# xunit - c#

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?

Related

XUnit mocking a method but doesn't return correct result

I should be getting a list of Product Types but GetProductTypesAsync() returns a null.
Is the class ProductTypeRepo meant to be mocked since it calls the acutal API.
Anyone able to assist?
namespace UnitTest.Service
{
public class ProductTypeServiceTests
{
private readonly IServiceProvider _serviceProvider;
private readonly Mock<IProductTypeRepo> _productTypeRepoMock;
private readonly Mock<ILogger> _LoggerMock
private IProductTypeService _productTypeService;
public ProductTypeServiceTests()
{
_productTypeRepoMock = new Mock<IProductTypeRepo>();
_LoggerMock= new Mock<ILogger>();
_productTypeService = new ProductTypeService(_productTypeRepoMock.Object, _LoggerMock.Object);
}
[Fact]
public async Task GetProductType_ReturnOKStatusCode()
{
var serviceResponse = await _productTypeService.GetProductTypesAsync();
Assert.Equal(
expected: serviceResponse,
actual: serviceResponse
);
}
}
}
--
namespace Service.ProductType
{
public class ProductTypeService : IProductTypeService
{
private readonly IProductTypeRepo _repository;
private readonly ILogger _Logger;
public ProductTypeService(IProductTypeRepo repository, ILogger logger)
{
_repository = repository;
_logger = logger;
}
public async Task<List<Domain.DTO.ProductTypeResponse>> GetProductTypesAsync()
{
var productTypes = await _repository.GetProductTypesAsync();
if (productTypes == null)
{
throw new ProductTypeNotFoundException($"No Product Types were retrieved");
}
return productTypes;
}
}
}
xxxxxxxxxx xxxxxxxx xxxxxx xxxxx
Nowhere in the test is the mock configured to return anything when invoked.
//...
[Fact]
public async Task GetProductType_ReturnOKStatusCode() {
//Arrange
List<Domain.DTO.ProductTypeResponse> expected = new List<Domain.DTO.ProductTypeResponse>();
//..add items to expected list if necessary
_productTypeRepoMock
.Setup(_ => _.GetProductTypesAsync()) //<-- when this is invoked
.ReturnsAsync(expected); //<-- return something.
//Act
List<Domain.DTO.ProductTypeResponse> actual = await _productTypeService.GetProductTypesAsync();
//Assert
Assert.Equal(expected, actual);
}

getting an error The following constructor parameters did not have matching fixture data: PostgreSqlResource resource

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()
}
}

Sequence contains no matching element error when returning class Type of Interface using IsAssignableFrom

This is a follow up question to another post I created around implementing a UI test solution that could toggle which classes to execute code from based on interfaces. The whole goal was to re use test code on versions of apps that are identical (Web vs WPF).
The code compiles fine, but after the test is ran it bombs out on the GetPageModelType method call. Below is my implementation pretty much identical to the linked post, with a few minor adjustments to abstract some of the page object creation on a TestClassBase
UI Test that can determine which classes to execute code from at runtime using interfaces
Interface and corresponding Page Object classes
public interface ILogin
{
void Login(string username, string password);
}
public class WebLogin : ILogin
{
private readonly IWebDriver driver;
public WebLogin(IWebDriver driver)
{
this.driver = driver;
}
public void Login(string username, string password)
{
Console.WriteLine("Web Success!");
}
}
public class WPFLogin : ILogin
{
private readonly WindowsDriver<WindowsElement> session;
public WPFLogin(WindowsDriver<WindowsElement> session)
{
this.session = session;
}
public void Login(string username, string password)
{
Console.WriteLine("WPF Success!");
}
}
Page Object factory classes
public interface IPageModelFactory
{
ILogin CreateLogin();
}
public class WebPageModelFactory : IPageModelFactory
{
private readonly IWebDriver driver;
public WebPageModelFactory(IWebDriver driver)
{
this.driver = driver;
}
public ILogin CreateLogin()
{
return new WebLogin(driver);
}
}
public class WPFPageModelFactory : IPageModelFactory
{
private readonly WindowsDriver<WindowsElement> session;
public WPFPageModelFactory(WindowsDriver<WindowsElement> session)
{
this.session = session;
}
public ILogin CreateLogin()
{
return new WPFLogin(session);
}
}
public class PageModelFactory
{
private readonly object client;
public PageModelFactory(object client)
{
this.client = client;
}
// Create Page Objects
public ILogin CreateLoginPage()
{
var pageModelType = GetPageModelType<ILogin>();
var constructor = pageModelType.GetConstructor(new Type[] { client.GetType() });
return (ILogin)constructor.Invoke(new object[] { client });
}
private Type GetPageModelType<TPageModelInterface>()
{
return client.GetType().Assembly.GetTypes().Single(type => type.IsClass && typeof(TPageModelInterface).IsAssignableFrom(type));
}
}
TestClassBase - base class for tests, simplifies test scripts
[TestFixture]
public class TestClassBase
{
// WinAppDriver variables
private static string WinAppDriverExe = "C:\\Program Files (x86)\\Windows Application Driver\\WinAppDriver.exe";
private string WindowsApplicationDriverUrl = "http://127.0.0.1:4723";
// Sessions
public WindowsDriver<WindowsElement> session;
public IWebDriver driver;
// Declare Page Objects
public ILogin login = null;
[SetUp]
public void SetUp()
{
if (GlobalData.targetHost.Equals("WPF"))
{
// Capabilities
AppiumOptions appCapabilities = new AppiumOptions();
appCapabilities.AddAdditionalCapability("app", GetExeFile());
appCapabilities.AddAdditionalCapability("appWorkingDir", GetWorkingDirectory());
// Create Session
session = new WindowsDriver<WindowsElement>(new Uri(WindowsApplicationDriverUrl), appCapabilities, TimeSpan.FromMinutes(3));
session.Manage().Window.Maximize();
// Pass session to page objects
PageModelFactory wpfPages = new PageModelFactory(session);
login = wpfPages.CreateLoginPage();
} else if (GlobalData.targetHost.Equals("Web"))
{
}
}
[TearDown]
public void TearDown()
{
// Clean up code...
}
}
LoginTests
public class LoginTests : TestClassBase
{
[Test]
public void Login()
{
// Login
login.Login("", "");
}
}
Whats not pictured above is my GlobalData.cs class which just contains a bunch of hardcoded variables that are used in the tests. I have the targetHost variable set to "WPF" while testing this against the WPF host. The StartUp code does launch the app as expected, it fails when we call GetPageModelType on PageModelFactory.CreateLoginPage();
I wasn't able to see this in my answer on your original question. The assembly in which the "client" resides and the assembly in which the page models reside are different. That means the PageModelFactory will need a second constructor parameter to know which assembly to search when initializing new page models:
public class PageModelFactory
{
private readonly object client;
private Assembly Assembly => GetType().Assembly;
public PageModelFactory(object client)
{
this.client = client;
}
// Create Page Objects
public ILogin CreateLoginPage()
{
var pageModelTypes = GetPageModelTypes<ILogin>();
var constructorSignature = new Type[] { client.GetType() };
foreach (var type in pageModelTypes)
{
var constructor = type.GetConstructor(constructorSignature);
if (constructor != null)
return (ILogin)constructor.Invoke(new object[] { client });
}
throw new InvalidOperationException($"No class found implementing ILogin with a constructor that accepts {client.GetType().FullName} as an argument in assembly {Assembly.Name}");
}
private IEnumerable<Type> GetPageModelTypes<TPageModelInterface>()
{
return Assembly.GetTypes()
.Where(type => type.IsClass
&& typeof(TPageModelInterface).IsAssignableFrom(type));
}
}

how to cover both constructor argument null exception and catch block for method `DoMethod()`

I have below unit test C# code,
public class ServiceTest
{
public readonly Service _sut;
private readonly Mock<IServiceClient> _serviceClientMock = new Mock<IServiceClient>();
private readonly Mock<ILogger<Service>> _loggerMock = new Mock<ILogger<Service>>();
public ServiceTest()
{
_sut = new Service(_serviceClientMock.Object, _loggerMock.Object);
}
[Fact]
public void Constructor_throws_Exception()
{
Assert.Throws<ArgumentNullException>(() => new Service(null, null));
}
[Fact]
public async Task Do_Test_For_DoMethod()
{
await _sut.DoMethod();
}
}
I have Constructor_throws_Exception which only covers one argument null exception, but not the other. How to cover both argument null exception plus the catch block for method? Is there a way I can merge with all in a single test? I am using xUnit.
You have to create a unique test for each invalid combination. Could be something like this:
public static IEnumerable<object[]> GetInvalidConstructorArguments()
{
yield return new object[] { new Mock<IServiceClient>().Object, null };
yield return new object[] { null, new Mock<ILogger<Service>>().Object };
}
[Theory]
[MemberData(nameof(GetInvalidConstructorArguments))]
public void ThrowsOnNullArgument(IServiceClient serviceClient, ILogger<Service> logger)
{
Assert.Throws<ArgumentNullException>(() => new Service(serviceClient, logger));
}
Getting a working mock for the ILogger<> is more complicated then it seems in the first spot. The problem is, that all convenient methods are extensions methods, which can't be mocked. Under the hood, all of these methods will call the Log<TState>() method which must be mocked. Thankfully to this answer, this can be done as follows:
public class MyTests
{
[Fact]
public void ExceptionShouldBeWrittenToLog()
{
// Instruct service client to throw exception when being called.
var serviceClient = new Mock<IServiceClient>();
var exception = new InvalidOperationException($"Some message {Guid.NewGuid()}");
serviceClient.Setup(s => s.Do()).Throws(exception);
// Create a strict mock, that shows, if an error log should be created.
var logger = new Mock<ILogger<MyService>>(MockBehavior.Strict);
logger.Setup(l => l.Log(
LogLevel.Error,
It.IsAny<EventId>(),
It.Is<It.IsAnyType>((o, t) => o.ToString() == exception.Message),
It.IsAny<InvalidOperationException>(),
It.IsAny<Func<It.IsAnyType, Exception, string>>()));
// Setup SUT and call method.
var service = new MyService(serviceClient.Object, logger.Object);
service.DoSomething();
// Check if method of logger was being called.
logger.VerifyAll();
}
}
public interface IServiceClient
{
public void Do();
}
public class MyService
{
private readonly IServiceClient serviceClient;
private readonly ILogger<MyService> logger;
public MyService(IServiceClient serviceClient, ILogger<MyService> logger)
{
this.serviceClient = serviceClient;
this.logger = logger;
}
public void DoSomething()
{
try
{
serviceClient.Do();
}
catch (Exception ex)
{
logger.LogError(ex.Message);
}
}
}

How to write xUnit Test for a method which calls another method in its body?

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>

Categories