I am Making Mock of Register Agency User But It showing some of its attribute Null.
I am new and I don't understand this.
I am trying to make Mock of Register Agency User that is the model
[TestMethod]
public async Task ABCreateActionResult_ReturnsBadRequest_Badrequest()
{
RegisterAgencyUserRequest mock = new Mock<RegisterAgencyUserRequest>().Object;
var controller = _accountController.RegisterAgencyUser(mock);
JsonResult viewResult = (JsonResult)await _accountController.RegisterAgencyUser(mock);
}
Here is what I have to Test
public async Task<IActionResult> RegisterAgencyUser([FromBody] Models.Request.RegisterAgencyUserRequest request)
{
JsonContentResult jsonContentResult = new JsonContentResult();
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (string.IsNullOrEmpty(request.InvitationCode) || string.IsNullOrWhiteSpace(request.InvitationCode))
return Json(new SharedResponse(AppConstants.ServiceReponses.Error, "A user can't be registered without invitation"));
var invitationDetails = _inviteRepository.GetInvitaionCodeDetails(request.InvitationCode);
if (invitationDetails.Type != (int)InviteType.Agency)
{
return Json(new SharedResponse(AppConstants.ServiceReponses.Error, "Invalid invitation code"));
}
//...
You only mock dependencies to your class that you are testing. So you don't need to mock a POCO. Just set it up with dummy data like below:
var model = new RegisterAgencyUserRequest
{
Address = "Value1",
AgencyName = "Value2",
//...
};
and use it like below:
var controller = _accountController.RegisterAgencyUser(model);
Your dependency for the method is:
_inviteRepository.GetInvitaionCodeDetails()
so you need to mock the _inviteRepository and inject it into the subject controller under test when initializing.
You need to setup something on the mock, your code just creates an empty object.
var mock = new Mock<RegisterAgencyUserRequest>();
mock.Setup(x => x.Address).Returns(() => "some address");
RegisterAgencyUserRequest request = mock.Object;
Edit: The answer from Azhar Khorasany explains how it should be done, by not mocking the POCO, but the service/repository that you use in your test.
Related
I'm trying to learn Unit testing in .NET 6 by testing a controller function GetProduct. The problem is I get null returned in the variable var product = await _productController.GetProduct(productId);. As you can see in the picture below, the Result is ok but the Value, where the ServiceResponse<Product> was suppose to be is null.
Here is the controller function:
public class ProductController : ControllerBase
{
private readonly IProductService _productService;
public ProductController(IProductService productService)
{
_productService = productService;
}
[HttpGet("{productId}")]
public async Task<ActionResult<ServiceResponse<Product>>> GetProduct(int productId)
{
var result = await _productService.GetProductAsync(productId);
return Ok(result);
}
}
Here is the Test:
public class ProductControllerTest
{
private readonly ProductController _productController;
private readonly Mock<IProductService> _productService = new Mock<IProductService>();
public ProductControllerTest()
{
_productController = new ProductController(_productService.Object);
}
[Test]
public async Task GetProducts_ReturnsProduct_IfProductExists()
{
//Arange
var productId = 1;
var prodData = new Product
{
Id = productId,
Title = "null"
};
var prductResponse = new ServiceResponse<Product>
{
Data = prodData,
Success = true ,
Message = ""
};
_productService.Setup(x => x.GetProductAsync(productId)).ReturnsAsync(prductResponse);
//Act
var product = await _productController.GetProduct(productId);
//Assert
Assert.That(product?.Value?.Data?.Id, Is.EqualTo(productId));
}
}
This behavior is observed due to overloaded operators on ActionResult<T> class.
Since the method, OK(value) returns an instance of OKObjectResult and the return type of controller method is of type ActionResult<ServiceResponse<Product>> the returned OKObjectResult instance is wrapped in an instance of ActionResult<T> and is exposed by the Result property. Hence typecasting the Result property (as shown by #BennyM) to OKObjectResult works.
Please note that the assertion would have succeeded had the controller method returned the ServiceResponse<Product> directly without modifying the return type on controller's method.
While this explains the behavior, I personally feel there is a better way to test controllers. This MSDN Article explains about integration testing. One can effectively unit test all the dimensions of the controllers - authentication, validation, (de)serialization, etc - by mocking the immediate dependencies of the respective controllers.
Since you are returning with an Ok call in your controller you can add a cast to the unit test.
var result = (await _productController.GetProduct(productId)).Result as OkObjectResult;
Assert.IsNotNull(result);
var returnedServiceResponse = result.Value as ServiceResponse<Product>;
Assert.That(returnedServiceResponse ?.Data?.Id, Is.EqualTo(productId));
Also you don't have to use Actionresult. You can also just return your service response
[HttpGet("{productId}")]
public async Task<ServiceResponse<Product>> GetProduct(int productId)
{
var result = await _productService.GetProductAsync(productId);
return result;
}
This will also make the test a bit easier as no need to use the OkObjectResult.
I am trying to mock my service's create method like this in the class constructor:
serviceMock.Setup(p => p.AddClinic(GetTestClinicModel()))
.Returns(GetTestClinic());
Mock Model and Mock Entity
private CreateClinicBindingModel GetTestClinicModel()
{
return new CreateClinicBindingModel()
{
Name = "Clinic-3"
};
}
private Clinic GetTestClinic()
{
return new Clinic()
{
Id = 3,
Name = "Clinic-3"
};
}
Test Method
[Fact]
public void Add_ValidObjectPassed_ReturnsCreatedResponse()
{
// Act
var createdResponse = controller.Add(GetTestClinicModel());
// Assert
Assert.IsType<CreatedAtActionResult>(createdResponse);
}
Controller Add Method
[HttpPost("create")]
public IActionResult Add(CreateClinicBindingModel model)
{
if (!ModelState.IsValid)
{
return BadRequest();
}
var entity = _service.AddClinic(model);
return Created(entity);
}
So my problem is test getting failure and when I debug _service.AddClinic() method it returns null.
The mock service does not return the expected Entity (Clinic).
How can I solve this?
The issue is that the setup expects the specific instance created when GetTestClinicModel() is invoked.
However that same instance is not used when exercising the test as a totally new instance is created when GetTestClinicModel() is invoked again.
Thus the mock will return null since there are separate instances.
Consider changing the setup to use an argument matcher like It.Is<T>()
serviceMock
.Setup(_ => _.AddClinic(It.Is<CreateClinicBindingModel>(m => m.Name == "Clinic-3")))
.Returns(GetTestClinic());
The above setup tells the mock to behave as expected when it gets an instance that matches the provided predicate
I am implemented my business logic using repository pattern. I basically have Approve method in my controller . I am calling the service method ApproveUserChangeRequest
which in turn invokes GetUserChangeRequest and ApproveUserChangeRequest in the UnitofWork class. I would like to know if this is standard or better way of doing it
Please bare in mind in to test the service methods
UserConroller
[HttpPost]
[AllowAnonymous]
[Route("approve-change-request")]
public IActionResult ApproveUserChangeRequest([FromBody] ApproveUserChangeRequests approveUserChangeRequests)
{
if (!ModelState.IsValid)
{
return BadRequest(new ResponseModel()
{
ResponseMessages = new Dictionary<string, string[]>
{
{ "Errors", ModelState.Values.SelectMany(x => x.Errors).Select(x => x.ErrorMessage).ToArray() }
}
});
}
var result = _userService.ApproveUserChangeRequest(approveUserChangeRequests);
var message = string.Empty;
if (result.Succeeded)
{
return Ok(new ResponseModel()
{
ResponseMessages = new Dictionary<string, string[]>
{
{ "Info", new string[] { $"True" } }
}
});
}
message = string.Join(";", result.Errors.Select(x => $"Code: {x.Code}. Description: {x.Description}"));
_logger.Error(new IdentityException($"Error approving user change requests. Message: {message}"));
return BadRequest();
}
UserService class
public IdentityResult ApproveUserChangeRequest(ApproveUserChangeRequests approveUserChangeRequests)
{
var userChangeRequest = _userUow.GetUserChangeRequest(approveUserChangeRequests.UserChangeRequestID);
IdentityResult result = _userUow.ApproveUserChangeRequest(userChangeRequest, approveUserChangeRequests.ApprovedByAuthUserId, approveUserChangeRequests.AuthApplicationName);
return result;
}
UnitofWork class (uow)
public UserChangeRequest GetUserChangeRequest(int userChangeRequestId)
{
return UserChangeRequestRepository.GetQueryable(x =>
x.Id == userChangeRequestId)
.FirstOrDefault();
}
public IdentityResult ApproveUserChangeRequest(UserChangeRequest userChangeRequest, int approvedByAuthUserId, string authApplicationName)
{
var idResult = IdentityResult.Success;
// Check if UserChangeRequest is still Pending
bool isUserChangeRequestPending = UserChangeRequestRepository.GetQueryable(x => x.Id == userChangeRequest.Id && x.ChangeStatus == "Pending").Any();
if (isUserChangeRequestPending && approvedByAuthUserId > 0)
{
// Inserting record in the UserChangeRequestApproval table
InsertUserChangeRequestApproval(userChangeRequest);
SaveContext();
//Updating the user details in IdentityDB, ClientCompanyContact and AuthUser tables
UpdateUserDetails(userChangeRequest, authApplicationName);
}
else
{
idResult = IdentityResult.Failed(new IdentityError { Description = "No userchange request to approve" });
}
return idResult;
}
It's important to only test each part of your application in isolation. When we test public IActionResult ApproveUserChangeRequest we only want to ensure that it's doing its own job correctly. Anything that it calls should be mocked, and tested separately.
For this you will need to create interfaces for your repository, and your UnitOfWork class. This will allow them to be mocked, and their behaviour simulated.
You should also allow these classes to be injected into the consuming class using Dependency Injection, for example:
private readonly IUserService _userService;
public MyController(IUserService userService)
{
_userService = userService;
}
public IActionResult ApproveUserChangeRequest([FromBody] ApproveUserChangeRequests approveUserChangeRequests)
{
// ... snip
// this now uses the instance that was provided by dependency injection
var result = _userService.ApproveUserChangeRequest(approveUserChangeRequests);
}
You would then be able to test your class/method, whilst mocking the behaviour of your user service. The following example uses Moq, but you could use another mocking framework.
public void ApproveUserChangeRequest_PassesApproveChangeRequestsModelToService()
{
// mock the user service
var userService = new Mock<IUserService>();
// provide the controller with the user service
var controller = new MyController(userService);
// create the model for the request
var model = new ApproveUserChangeRequests();
// test the method
controller.ApproveUserChangeRequest(model);
// make sure that userService.ApproveUserChangeRequest was called with the correct arguments
userService.Verify(u => u.ApproveUserChangeRequest(model));
}
In the unit tests for the Controller, you only need to check that ApproveUserChangeRequest is doing it's job correctly. That is
verifying your model
raising an error if the model isn't valid
calling the user service if it is valid
sending you the correct response if it's successful
logging correctly to your logger
responding with bad request if appropriate
These should all be checked for in separate unit tests.
You should also then write tests for your UserService, and your UnitOfWork class. Only write tests for things that those classes are responsible for. If you find that the class is responsible for too many things, refactor your class until it obeys the single responsibility principle, this will greatly aid your ability to test your code.
I have built unit testing for my service layer. I have not used Mock as I think that since you are adding/deleting/querying a database, why query a mock as the results could be different, but that isn't what I am asking.
Now I am using Moq to test my web api layer. I think that this is fine, as if all my tests pass on the service layer, it is fine to mock the services to test the web api.
I have managed to write a test for my GetAsync method and it works all fine, like so
Here is the controller:
public async Task<IHttpActionResult> GetAsync(long id)
{
Content content = await _service.GetAsync(id);
ContentModel model = Mapper.Map<ContentModel>(content);
return Ok(model);
}
Here is the test:
[TestMethod]
public void Content_GetAsync()
{
// arrange
var mockService = new Mock<IContentService>();
mockService.Setup(x => x.GetAsync(4))
.ReturnsAsync(new Content
{
Id = 4
});
// setup automapper
AutoMapperConfig.RegisterMappings();
// act
var controller = new ContentController(mockService.Object);
var actionResult = controller.GetAsync(4).Result;
var contentResult = actionResult as OkNegotiatedContentResult<ContentModel>;
// assert
Assert.IsNotNull(contentResult);
Assert.IsNotNull(contentResult.Content);
Assert.AreEqual(4, contentResult.Content.Id);
}
I believe I wrote this correctly, and it seems to work. Now I would like to test my PostAsync method to add an item. The controller looks like this:
public async Task<IHttpActionResult> PostAsync(ContentModel model)
{
Content content = Mapper.Map<Content>(model);
await _service.AddAsync(content);
return Created<ContentModel>(Request.RequestUri, Mapper.Map<ContentModel>(content));
}
And here is the test:
[TestMethod]
public void Content_PostAsync()
{
var mockService = new Mock<IContentService>();
mockService.Setup(e => e.AddAsync(new Content()))
.ReturnsAsync(1);
// setup automapper
AutoMapperConfig.RegisterMappings();
// act
var controller = new ContentController(mockService.Object);
var actionResult = controller.PostAsync(new ContentModel {
Heading = "New Heading"
}).Result;
var contentResult = actionResult as CreatedAtRouteNegotiatedContentResult<ContentModel>;
// assert
Assert.IsNotNull(contentResult);
Assert.IsNotNull(contentResult.Content);
Assert.AreEqual("New Heading", contentResult.Content.Heading);
}
Now when I run this, I get an error:
null reference exception. "Request" from the Request.RequestUri is null.
So I changed my controller and tests to this, to try and mock it.
Test code:
public Task<IHttpActionResult> PostAsync(ContentModel model)
{
return PostAsync(model, Request);
}
/// Unit testable version of above. Cannot be accessed by users
[NonAction]
public async Task<IHttpActionResult> PostAsync(ContentModel model, System.Net.Http.HttpRequestMessage request)
{
Content content = Mapper.Map<Content>(model);
await _service.AddAsync(content);
return Created<ContentModel>(request.RequestUri, Mapper.Map<ContentModel>(content));
}
Controller code:
[TestMethod]
public void Content_PostAsync()
{
// arrange
var mockRequest = new Mock<System.Net.Http.HttpRequestMessage>();
mockRequest.Setup(e => e.RequestUri)
.Returns(new Uri("http://localhost/"));
var mockService = new Mock<IContentService>();
mockService.Setup(e => e.AddAsync(new Content()))
.ReturnsAsync(1);
// setup automapper
AutoMapperConfig.RegisterMappings();
// act
var controller = new ContentController(mockService.Object);
var actionResult = controller.PostAsync(new ContentModel {
Heading = "New Heading"
}, mockRequest.Object).Result;
var contentResult = actionResult as CreatedAtRouteNegotiatedContentResult<ContentModel>;
// assert
Assert.IsNotNull(contentResult);
Assert.IsNotNull(contentResult.Content);
Assert.AreEqual("New Heading", contentResult.Content.Heading);
}
Now I get an error saying:
Invalid setup on a non-virtual (overridable in VB) member: e => e.RequestUri
Can someone please, please help me with this. I am sure I am using Mock correctly in all tests, but unit testing is new to me, so maybe I am just not doing something right.
With Moq you can only mock virtual/absrtact members. The RequestUri is not a virtual member of HttpRequestMessage, hence the error message.
You should be able to just new a HttpRequestMessage directly without mocking it and pass that in.
var request = System.Net.Http.HttpRequestMessage>();
request.RequestUri = new Uri("http://localhost/");
// act
var controller = new ContentController(mockService.Object);
var actionResult = controller.PostAsync(new ContentModel {
Heading = "New Heading"
}, request).Result;
Ned's answer is correct. Moq is a constrained mocking library, meaning that it generates dynamic subclasses of the classes you mock at runtime. These subclasses cannot override methods if they are not declared virtual in the mocked class. You can find more information on constrained vs. unconstrained mocking libraries in the art of unit testing.
That's why people that use a mockist style of unit testing prefer to mock against interfaces instead of concrete classes, as the generated mock subclasses can easily override (or rather, implement) the methods on the interface.
I am writting unit test cases. I am using nunit and rhino mock.
Method which is i am testing is
public ActionResult Details()
{
EmployeeDTO employee = this.EmployeeService.GetLoggedInEmployee();
EmployeeModel model = assembler.ToEmployeeModel(employee);
model.Title = GetEmployeeNameTitle(employee);
model.Controller = "LoanOfficer";
model.SelectedTab = MainNavTabs.LoanOfficerDetails;
return View(model);
}
And test case written is
[Test]
public void TestDetails()
{
EmployeeDTO employee = new EmployeeDTO();
EmployeeService.Stub(a => a.GetLoggedInEmployee()).Return(employee);
EmployeeModel model = new EmployeeModel{ Title = UtilityTests.Title, };
assembler.Stub(b => b.ToEmployeeModel(employee)).Return(model);
controller.Details();
// Assert
}
I have done
private ILoanModelAssembler loanAssembler;
loanAssembler = TestUtility.DynamicMock<ILoanModelAssembler>();
but still here model is null ? Is there is any way to correct it in test method?
It's null because your you're not taking control of the actual instance of EmployeeService from within your test. How is your EmployeeService dependency being added to the controller? Is it an interface? You would need it to be an interface so that Rhino Mocks can mock it and you would need to inject it into the constructor of your controller so that you can inject your mocked instance into your test. Something like this:
private IEmployeeService employeeService;
public EmployeeController(IEmployeeService employeeService)
{
this.employeeService = employeeService;
}
Then in your test you can say:
var employeeServiceStub = MockRepository.GenerateStub<IEmployeeService>();
var employee = new EmployeeDTO();
employeeServiceStub.Stub(a => a.GetLoggedInEmployee()).Return(employee);