Test Fail on simulating inserting in database - c#

Please find link to the project source: https://bitbucket.org/danchi/salescheese/src/master/
There I have problem with testing one domain entity
public class RegisterStockUseCaseUnitTests
{
[Fact]
public async void Can_Register_Stock()
{
//arrange
var mockProductRepository = new Mock<IProductRepository>();
var mockStockRepository = new Mock<IStockRepository>();
var mockUserRepository = new Mock<IUserRepository>();
var mockStorageLocationRepository = new Mock<IStorageLocationRepository>();
mockProductRepository.Setup(repo => repo.FindById(It.IsAny<int>()))
.Returns(Task.FromResult(true));
mockUserRepository.Setup(repo => repo.FindById(It.IsAny<string>()))
.Returns(Task.FromResult(true));
mockStorageLocationRepository.Setup(repo => repo.FindById(It.IsAny<int>()))
.Returns(Task.FromResult(true));
var useCase = new RegisterStockUseCase(mockStockRepository.Object,mockProductRepository.Object,mockUserRepository.Object, mockStorageLocationRepository.Object);
var mockOutputPort = new Mock<IOutputPort<RegisterStockResponse>>();
mockOutputPort.Setup(outputPort => outputPort.Handle(It.IsAny<RegisterStockResponse>()));
//act
var response =
await useCase.Handle(new RegisterStockRequest(5, "userId", StockType.Output, UnitOfMeasure.Grams,10,1),
mockOutputPort.Object);
//assert
Assert.True(response);
}
}
When I debug I'm getting: System.NullReferenceException: 'Object reference not set to an instance of an object.'
I can not figure what, can you please help me ?
P.S. Any idea how to improve tests are welcome. All of them are creating with TDD.
Thanks
[Update 1]

Oh I had forgot to setup mocking for creating stock, So I had missing next part of the code
mockStockRepository.Setup(repo => repo.Create(It.IsAny<Stock>()))
.Returns(Task.FromResult(new CreateStockResponse(1, true)));

Related

How do I mock the NestClient DebugInformation in C#?

I'd like to Moq the response from the ElasticClient to show an error or some information in the DebugInformation property.
I have the following:
ISearchResponse<person> personResponse = new SearchResponse<person>();
personResponse.ApiCall = new ApiCallDetails
{
Success = false,
};
personResponse.DebugInformation = "Something happened"; //This is not allowed
_elasticClient.Setup(s =>
s.Search<person>(
It.IsAny<Func<SearchDescriptor<person>, ISearchRequest>>()))
.Returns(personResponse);
I am unable to assign to DebugInformation as it is readonly. Any ideas?
Someone suggested I Moq the Interface of the response instead
So I mocked it Like this
Mock<ISearchResponse<person>> mockResponse = new Mock<ISearchResponse<person>>();
mockResponse.Setup(s => s.ApiCall.DebugInformation).Returns("Something");
mockResponse.Setup(s => s.ApiCall.Success).Returns(false);
mockResponse.Setup(s => s.Hits).Returns(new List<IHit<person>>());
_elasticClient.Setup(s =>
s.Search<person>(
It.IsAny<Func<SearchDescriptor<person>, ISearchRequest>>()))
.Returns(mockResponse.Object);
... and this works!

Unable to mock Auto Mapper in .Net core

net core 3.1 and I am using auto mapper. I am writing unit test cases and I have below piece of code
var coOrdinateReferenceSystemNames = await _coordinateReferenceSystemRepository.GetAsync(x => x.CoordinateReferenceSystemName.Contains(request.searchName)).ConfigureAwait(false);
IEnumerable<CoordinateReferenceSystemModel> CoordinateReferenceSystemList = _mapper.Map<IEnumerable<CoordinateReferenceSystemModel>>(coOrdinateReferenceSystemNames);
Below is my unit test case.
Func<IEnumerable<CoordinateReferenceSystem>> func = () => { return new List<CoordinateReferenceSystem>() { coordinateReferenceSystemModel }; };
this.mockMapper.Setup(x => x.Map<IEnumerable<CoordinateReferenceSystem>>(It.IsAny<IEnumerable<CoordinateReferenceSystemModel>>())).Returns(func);
Which throws below error
One or more errors occurred. (IMapperBase.Map>([CoordinateReferenceSystem]) invocation failed with mock behavior Strict. All invocations on the mock must have a corresponding setup.)
Can someone help me to understand this error and Which part I am doing wrong here. Any help would be appreciated. Thanks
Hi I have added mock mapper as below and started working fine.
private CoordinateReferenceSystemAr CreateCoordinateReferenceSystemAr()
{
var mockMapper = new MapperConfiguration(cfg =>
{
cfg.AddProfile(new MappingProfile());
});
var mapper = mockMapper.CreateMapper();
return new CoordinateReferenceSystemAr(this.mockApiRequestHandler.Object,this.mockUnitOfWork.Object, mapper);
}

Moq not matching method

I have a method
Task<Document> GetCampaignById(Tenant tenant, string language, string campaignId);
that I am trying to mock:
mockLocator.Setup(l => l.GetCampaignById(
It.IsAny<Tenant>(),
It.IsAny<string>(),
It.IsAny<string>()))
.Returns(Task.FromResult(dummy));
I did, at first have "not set up" output but I am not getting any at all now and the test just shows as failed. I have tried changing to ReturnsAsync(dummy) but that did not alter my output at all. moq is set to strict but I don't think that should matter.
As far as I can tell I am setting this up with the correct parameter types and the correct return type but the test seems to fail before it even starts. Can anyone shed any light on this?
Full Test
[TestCase(1)]
[TestCase(2)]
[TestCase(3)]
[TestCase(4)]
[TestCase(5)]
public async Task ShouldCallUpdaterForEveryTenantResolved(int tupleCount)
{
// Arrange
var tenantTuples = CreateTenantTuples(tupleCount);
var mockTenantResolver = MockRepository.Create<ITenantResolver>();
mockTenantResolver.Setup(tr => tr.GetTenantTuples(It.IsAny<string>()))
.Returns(tenantTuples);
var mockCampaignIngestionService = MockRepository.Create<ICampaignIngestionService>();
var dummy = new Document();
var mockLocator = MockRepository.Create<IVehicleSearchStockUpdater>();
mockLocator.Setup(l => l.GetCampaignById(
It.IsAny<Tenant>(),
It.IsAny<string>(),
It.IsAny<string>()))
.Returns(Task.FromResult(dummy));
mockLocator.Setup(l => l.UpsertNewStockLevel(
It.IsAny<Document>(),
It.IsAny<OmegaConnector.Functions.PartnerCommunicator.Models.ChangeStockInfo>()))
.Returns(Task.FromResult(dummy));
var sut = new CampaignIngestionProcessor(
mockTenantResolver.Object,
mockCampaignIngestionService.Object,
mockLocator.Object);
var data = GetSimpleTestData();
data.NewStock = 5;
// Act
await sut.SubmitChangeStock(data);
// Assert
mockLocator.Verify(l => l.GetCampaignById(
It.IsAny<Tenant>(),
It.IsAny<string>(),
It.IsAny<string>()),
Times.Exactly(tupleCount)
);
mockLocator.Verify(l => l.UpsertNewStockLevel(
It.IsAny<Document>(),
It.IsAny<OmegaConnector.Functions.PartnerCommunicator.Models.ChangeStockInfo>()),
Times.Exactly(tupleCount)
);
}

Unit testing Web API Controller: Error fetching result

I'm new to unit testing in ASP.NET so please forgive my ignorance on this. I'm trying to test my controller.
This is the function in my controller which I'm testing:
public IHttpActionResult GetCustId(string name)
{
var c_id = db.Customer.Where(s => (s.c_Name == name));
if (c_id == null)
{
return null;
}
return Ok(c_id);
}
And this is my unit test code:
public void GetName_ShouldReturnCorrectId()
{
var context = new TestSContext();
context.Customers.Add(new Customer { c_ID = 1, c_Name = "jonny"});
var controller = new CustomerController(context);
var result = controller.GetCustId("Johnny") as OkNegotiatedContentResult<Customer>; //ISSUE: Result is always NULL
Assert.IsNotNull(result);
Assert.AreEqual(1, result.Content.c_ID);
}
The issue is here:
var result = controller.GetServiceId("Johnny") as OkNegotiatedContentResult<Customer>
because it is always returning NULL.
BUT... If I use just this:
var result = controller.GetCustId("Johnny");
Then the result is not null. And the first assert passes.
But I can't use it because I'm not sure how to check the second assert statement without using result.Content. I'm really not sure what are the best practices to be testing in my case.
Appreciate any help.
You are trying to find "Johnny" (with 'h') when you have put "jonny" into your mock context thus method always returns null due to your if statement
if (c_id == null)
{
return null;
}
Adding to #nizzik's answer, which is correct based on your example, to avoid simple mistakes like that you should store your values in variables and reuse them to make sure that they are as intended.
public void GetName_ShouldReturnCorrectId() {
//Arrange
var name = "Johnny";
var expectedId = 1;
var context = new TestSContext();
context.Customers.Add(new Customer { c_ID = expectedId, c_Name = name});
var controller = new CustomerController(context);
//Act
var result = controller.GetCustId(name) as OkNegotiatedContentResult<Customer>;
//Assert
Assert.IsNotNull(result);
Assert.AreEqual(expectedId, result.Content.c_ID);
}
That way you can change any one of them and the test should execute as expected.

Is it possible to return a mock from another mock using Moq in C#?

I am using Moq as my mocking framework. As per the code below, I have two mocks setup and I would like to setup the second to return the first mock. Is this possible and if so how would I go about doing it? At the moment it says the mock being returned is an invalid candidate.
[SetUp]
private void SetupMarketRow()
{
var marketTotalRow = new Mock<ITotalRow>();
marketTotalRow.Setup(r => r.TotalBudgetCurrentFact).Returns(1860716);
marketTotalRow.Setup(r => r.TotalBudgetEvol).Returns(-26);
marketTotalRow.Setup(r => r.TotalBudgetPreviousFact).Returns(2514079);
var localMarketReport = new Mock<IReport>();
localMarketReport.Setup(r => r.TotalRow).Returns(marketTotalRow);
// Red swiggley here saying invalid candidate
}
You can access the actual Mocked ITotalRow using marketTotalRow.Object.
[SetUp]
private void SetupMarketRow()
{
var marketTotalRow = new Mock<ITotalRow>();
marketTotalRow.Setup(r => r.TotalBudgetCurrentFact).Returns(1860716);
marketTotalRow.Setup(r => r.TotalBudgetEvol).Returns(-26);
marketTotalRow.Setup(r => r.TotalBudgetPreviousFact).Returns(2514079);
var localMarketReport = new Mock<IReport>();
localMarketReport.Setup(r => r.TotalRow).Returns(marketTotalRow.Object);
// Red swiggley here saying invalid candidate
}
Changing the interface declaration from
MarketTotalRow TotalRow { get; }
to...
ITotalRow TotalRow { get; }
fixed the problem.

Categories