MOQ error setups not matched with Async / Await Unit Test - c#

I am trying to figure out what I am missing here. My test runs fine but my MOQ VerifyAll is throwing an exception.
[TestMethod]
public async Task ActionPlanDataProvider_GetActionPlanReferenceList_ReturnsValid()
{
try
{
//Arrange
Mock<IActionPlanDataProvider> moqAPlan = new Mock<IActionPlanDataProvider>();
//moqAPlan.Setup(x => x.GetActionPlanReferenceList()).ReturnsAsync(new ActionPlanReferenceList());
moqAPlan
.Setup(x => x.GetActionPlanReferenceList("1"))
.Returns(Task.FromResult(new ActionPlanReferenceList()));
//Act
var d = await moqAPlan.Object.GetActionPlanReferenceList("1234123");
//Assert
moqAPlan.VerifyAll();
}
catch (Exception ex)
{
string a = ex.Message;
throw;
}
}
The following setups were not matched...
I'm wondering if this is because the way async runs that my MOQ doesn't see mocked object method call?

That happens when the Setup is not used. You set up the mock to use GetActionPlanReferenceList("1") but called GetActionPlanReferenceList("1234123").
So according to moq what you executed didn't match what you setup.
You could either match the expected arguments or try
moqAPlan
.Setup(x => x.GetActionPlanReferenceList(It.IsAny<string>()))
.Returns(Task.FromResult(new ActionPlanReferenceList()));
which will let the method accept any string vai the It.IsAny<string>() expression argument

Related

How to Verify assert throw exception for the return list function C#

How do I use Assert (or other Test class) to verify that an exception has been thrown?
public async Task<IEnumerable<HHABranchAggregatorConfigurationDto>> HHABranchAggregatorDetails(int HHA, int UserId, int HHA_Branch_ID)
{
IEnumerable<HHABranchAggregatorConfigurationDto> hhabranchAggregatorsettingslists = new List<HHABranchAggregatorConfigurationDto>();
try
{
var EVVVendorMasterList = await _UAEVVVendorMasterRepository._HHA_Schedule_GetUAEVVVendorMaster(HHA, UserId, "EvvVendorMasterID,VendorName,isPrimary");
}
catch (Exception e)
{
_logger.LogError(e.Message);
}
return hhabranchAggregatorsettingslists;
}
Unit Test In this unit test trying to capture the null reference exception
[Fact]
public async Task Agency_Configuration_Should_Throw_Exception()
{
//Arrange
_UAEVVVendorMasterRepositoryMock.Setup(x => x._HHA_Schedule_GetUAEVVVendorMaster(It.IsAny<int>(), It.IsAny<int>(), It.IsAny<string>())).Throws<NullReferenceException>();
//Act
var hhabranchAggregatorsactuallist = await agencyConfigurations.HHABranchAggregatorDetails(1, 1, 3052);
//Assert
var ex = Assert.Throws<Exception>(() => hhabranchAggregatorsactuallist);
}
But while doing this getting this error message needs suggestion
Assert.Throws() Failure
Expected: typeof(System.Exception)
Actual: (No exception was thrown)
Use ThrowsAsync instead of Throws:
var ex = await Assert.ThrowsAsync<Exception>(async () => await agencyConfigurations.HHABranchAggregatorDetails(1, 1, 3052));
I assume because you catch the exception in the target method named "HHABranchAggregatorDetails", the Assert API doesn't notice it. You would need to either not catch or to rethrow it, I guess.
But of course its better in productive code to catch it ^^

Writing mocks using moq for a method

I have the method below I will like to unit test. I am using mstest. Notice how CatService
is used to call 2 other methods
This line of code gets a service of Type T
_provider.GetNecessaryService<IJohnsonProject>() gets a service of Type T
Here is the method
public async Task<(bool, string)> AddDataAsync(DataDto firstSet)
{
try
{
var CatService = _provider.GetNecessaryService<IJohnsonProject>();
var dto = _mapper.Map<MyDto>(firstSet);
var reply = await CatService.AddInfoAsync(dto);
if (!string.IsNullOrEmpty(firstSet.ImageMime) && firstSet.Image.Length > 0)
{
await CatService.AddPictureAsync(reply.Id, firstSet.Image, firstSet.ImageMime);
}
return (true, reply.Id);
}
catch (Exception ex)
{
return (false, ex.Message);
}
}
I started thinking I have to write some Mocks. The first one I have below should return a service type of T
[TestMethod]
public async Task MyFirstTest(){
var CatService = _mockprovider.Setup(x => x.GetNecessaryService<IJohnsonProject>());
}
What is the best way to Mock these two lines ?
var reply = await CatService.AddInfoAsync(dto);
await CatService.AddPictureAsync(reply.Id, firstSet.Image, firstSet.ImageMime);
_provider is a factory pattern, therefore you need to implement a mocked up version of the objects that it returns too:
var mockedJohnsonProject = new Mock<IJohnsonProject>();
mockedJohnsonProject.Setup(x=>x.AddInfoAsync(It.IsAny<MyDto>());
var CatService = _mockprovider.Setup(x => x.GetNecessaryService<IJohnsonProject>())
.Returns(mockedJohnsonProject.Object);

Mock function not throwing exception in c# unit test

Here is my unit test method
[Fact]
public void DealerSmsStatusTestTest_MustReturnInternalServerErrorIfMockMethodFails()
{
//Arrange
Mock<DBClass.IDealer> mock = new Mock<DBClass.IDealer>();
var exception = FormatterServices.GetUninitializedObject(typeof(System.Data.SqlClient.SqlException));
mock.Setup(x => x.GetDealerStatus(new System.Net.Http.HttpRequestMessage()))
.Throws((System.Data.SqlClient.SqlException)exception);
DealerSettingController controller = new DealerSettingController(mock.Object);
//Act
var result = controller.DealerSmsStatus();
//Assert
/*I will do assertion here*/
}
And here is my controller method
public IHttpActionResult DealerSmsStatus()
{
try
{
var result = _dealer.GetDealerStatus(Request);
return Json(new Models.Response(
Models.ResponseMessages.Success,
result)
);
}
catch (System.Data.SqlClient.SqlException)
{
return InternalServerError();
}
catch (System.Exception ex)
{
Logger.Error(ex, ex.Message, ex.StackTrace);
return InternalServerError();
}
}
When i debug the test, GetDealerStatus() method should return SqlException instead it returns null. In controller method var result always getting null. Any suggestions appreciated why it is not working.I want to throw SqlException through GetDealerStatus().
Here is debug mode result value image
You should use It.IsAny<System.Net.Http.HttpRequestMessage>() instead of new System.Net.Http.HttpRequestMessage() at Setup. Because you configured your method for concrete instance of System.Net.Http.HttpRequestMessage, at test it's not the same.
It's probably the matcher x.GetDealerStatus(new System.Net.Http.HttpRequestMessage())
new System.Net.Http.HttpRequestMessage() creates a new instance of a HttpRequestMessage which will not be equal to the Request you're passing into GetDealerStatus in your SUT.
Normally you'd use something like:
x.GetDealerStatus(It.IsAny<System.Net.Http.HttpRequestMessage>())
or
It.Is<System.Net.Http.HttpRequestMessage>(x => whatever specific equality conditions you want to match on)
if you want to narrow the match condition from just 'any'

Whats tests would sufficiently Unit Test a "Create" controller method in MVC?

I want to test this (Controller Method) :
public async Task<IActionResult> Create(SecurityQuestionViewModel securityQuestion)
{
if (ModelState.IsValid)
{
SecurityQuestion dataModel = new SecurityQuestion();
dataModel.questionText = securityQuestion.QuestionText;
await _securityRepository.AddAsync(dataModel);
return RedirectToAction("Index");
}
else
{
return View();
}
}
My unit test (so far) looks like this ?
public async Task ModelContainsNewObjectAfterCreate()
{
//Arrange
_repository = new Mock<ISecurityQuestionRepository>();
_repository.Setup(repo => repo.GetAllAsync()).Returns(Task.FromResult(securityQuestion()));
_controller = new SecurityQuestionsController(_repository.Object, _mapper);
SecurityQuestion dataModel = new SecurityQuestion();
dataModel.questionText = "This is the new added question";
SecurityQuestionViewModel sqvm = new SecurityQuestionViewModel();
sqvm.QuestionText = dataModel.questionText;
//Act
var result = await _controller.Create(sqvm);
//Assert
var viewResult = Assert.IsType<RedirectToActionResult>(result);
_repository.Verify(r => r.AddAsync(dataModel), Times.Once);
}
The viewResult passes.
The _repository verify does not.
It feels like I need to verify that the AddAsync method ran (would add a record to the existing repository). Perhaps my setup is wrong
It also feels like I need to validate the number of "questions" in the repository after the AddAsync method ran.
I am trying to understand what would constitute an adequate test and how to simulate the "Add" with the Moq.
Any insight would be appreciated.
This Post seems close to what I want.
You can test only following things in your action:
The case when the model is valid.
The case when the model is invalid.
There are only two cases. If the first case is satisfied you can verify that AddAsync() is executed with any parameter which is type SecurityQuestion.
You can mock AddAsync() like this:
repository.Setup(r => r.AddAsync(It.IsAny<SecurityQuestion>())
.Returns(Task.FromResult(false));
And verify:
repository.Verify(r => r.AddAsync(It.IsAny<SecurityQuestion>()), Times.Once);
That is all which you can!
You cannot mock SecurityQuestion model because it uses new keyword and your code which try to mock should be removed.
This is all you need to do because your entire logic is if/else statement. Everything else will be executed normally. Only another thing which can behave unexpectedly is if AddAsync() throws an exception.
The verify fails because the model was created within the method under test so it does not match. what you can do is use the It.Is with a predicate that matches the model properties
_repository.Verify(r => r.AddAsync(It.Is<SecurityQuestion>(m => m.questionText == dataModel.questionText)), Times.Once);

How to test a log method in catch block in Unit test

I have the following code for which I am writing a unit test
protected virtual string GetTokenFromTheWebrequest(WebRequest httpWebRequestObject)
{
try
{
HttpWebResponse responseHttpPostForToken = (HttpWebResponse)httpWebRequestObject.GetResponse();
string tokenJson = GetContentResponse(responseHttpPostForToken);
AccessToken accesstokenObj = DeserializeToAccessToken(tokenJson);
return accesstokenObj.Token;
}
catch (Exception Error)
{
Log.Debug("error");//I want to test this method
throw Error;
}
}
So,For this I have this unit test
[Test]
[ExpectedException(typeof(JsonReaderException))]
public void GetTokenFromTheWebrequestTestwithInValidHttpWebResponseOjectJsonReader()
{
var mockHttpWebResponse = new Mock<HttpWebResponse>();
var mockHttpWebRequest = new Mock<HttpWebRequest>();
var mockLog = new Mock<ILog>();
mockHttpWebRequest.Setup(c => c.GetResponse()).Returns(mockHttpWebResponse.Object);
mockedSurveyMonkeyAPIService.Setup(y => y.GetContentResponse(mockHttpWebResponse.Object)).Returns(TestData.TestData.SampleResponseStream);
mockedSurveyMonkeyAPIService.Setup(z => z.DeserializeToAccessToken(TestData.TestData.SampleResponseStream)).Throws(new JsonReaderException());
//mockLog.Setup(x => x.Debug("error")).Throws(new WebException());
var token = mockedSurveyMonkeyAPIService.Object.GetTokenFromTheWebrequest(mockHttpWebRequest.Object);
mockLog.VerifySet(x => x.Debug("error"),Times.Once); //its not going till this when i debug
}
Can anyone suggest how to check whether Log.Debug is called properly.
You don't seem to be testing any of your own code... you've mocked pretty much everything being used in that method. This begs the question what is actually being tested and the answer is that your implementation details are being tested, not any logic. You have even mocked the logger, so really you are testing the .NET try-catch mechanism here.
If you make any minor change to this method, your test will break even though the behaviour is the same. This is not the kind of test you want to shackle yourself to.
There are better ways of testing. For example, if you want to test your logger - test it in isolation of this method so you know your logger works. Don't test the logger by testing calls to it everywhere it is used.

Categories

Resources