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'
Related
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 ^^
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);
I am trying to unit test a method that throws an exception, and before throwing it has to perform a few tasks, like logging. I am using NSubstitute and can't get my head around this one.
so my test looks like this
[TestMethod]
[ExpectedException(typeof(IOException))]
public void RecordAnalyser_FileReadFailedInFirstAttempt_WarningLogged()
{
//Arrange
var fileMock = Substitute.For<IFile>();
fileMock.ReadLines(Arg.Any<string>()).Throws(new IOException());
//Act
var recordAnalyser = new RecordAnalyser(fileMock, logger); //--> throws exception.
//Assert
logger.Received(1).Warn(Arg.Any<string>(), Arg.Any<Exception>());
}
Now i want to assert if logger received a warning log, but since the line above sends an exception, and i have an expected exception attribute, test doesn't come to check for assertion.
One dirty code i can think of is to wrap the error statement in a try catch within the test, but its not the neatest.
//Act
try
{
var recordAnalyser = new RecordAnalyser(fileMock, logger);
}
catch (Exception)
{
// eat
}
Code under test -
public RecordAnalyser(IFile file, ILoggerService logger)
{
this.logger = logger;
try
{
names = file.ReadLines(Constants.Names).ToList();
}
catch (System.IO.IOException e)
{
logger.Error("Names file could not be read.", ex);
// How do I test above line without a try catch block in unit test
throw;
}
}
looking for suggestions here.
This may be an XY problem.
You are trying to test/assert multiple things in one test. hence the problem.
If the goal was just to test that the exception is thrown then great no try/catch and test would pass.
[TestMethod]
[ExpectedException(typeof(IOException))]
public void RecordAnalyser_Should_FailInFirstAttempt_When_FileRead() {
//Arrange
var fileMock = Substitute.For<IFile>();
fileMock.ReadLines(Arg.Any<string>()).Throws(new IOException());
//Act
var recordAnalyser = new RecordAnalyser(fileMock, logger); //--> throws exception.
}
In another test where you want to assert that something happens when the exception is thrown then you will need to catch the exception to allow the test to be exercised to completion and allow assertions to be verified.
[TestMethod]
public void RecordAnalyser_Should_LogWarning_When_FileReadFailedInFirstAttempt() {
//Arrange
var fileMock = Substitute.For<IFile>();
fileMock.ReadLines(Arg.Any<string>()).Throws(new IOException());
IOException error = null;
//Act
try {
var recordAnalyser = new RecordAnalyser(fileMock, logger); //--> throws exception.
} catch(IOException ex) {
error = ex; //catch and hold error for later
}
//Assert
if(error == null)
Assert.Failed("exception expected"); // error was not thrown.
logger.Received(1).Warn(Arg.Any<string>(), Arg.Any<Exception>());
}
You could use following Extension which provides the implementation of Assert.Throws(Action) and Assert.Throws(Action): https://github.com/bbraithwaite/MSTestExtensions
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
I have a unit test and am checking for null exceptions of my controller constructor for a few different services.
[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
In my controller constructor I have:
if (routeCategoryServices == null)
throw new ArgumentNullException("routeCategoryServices");
if (routeProfileDataService == null)
throw new ArgumentNullException("routeProfileDataService");
I have a unit test for each, but how can I distinguish between the two. I can leave the test as is as either of the checks could be throwing null so I want to test the exception by param name.
Is this possible?
You could explicitly catch the exception in your test and then assert the value of the ParamName property:
try
{
//test action
}
catch(ArgumentException ex)
{
Assert.AreEqual(expectedParameterName, ex.ParamName);
}
Lee's answer is great, but the test will only fail if an ArgumentException is thrown with the wrong parameter name. If no exception is thrown, the test will pass. To remedy this, I added a bool in my test like this
// Arrange
var expectedParamName = "param";
bool exceptionThrown = false;
// Act
try
{
new Sut(null);
}
// Assert
catch (ArgumentNullException ex)
{
exceptionThrown = true;
Assert.AreEqual(expectedParamName, ex.ParamName);
}
Assert.That(exceptionThrown);
See this: http://msdn.microsoft.com/en-us/library/ms243315.aspx
You can provide the expected message too:
[TestMethod]
[ExpectedException(typeof(ArgumentNullException), "routeCategoryServices")]
Requires two test cases though.
var exception = Assert.Throws<ArgumentNullException>(() => new Sut(...));
Assert.That(exception.ParamName, Is.EqualTo("routeCategoryServices");