model validation unittest using Moq - asp.net-mvc-3

Hi i am trying to validate model field as required but result is always comming null, I am expecting model will send me error as First name is requied but nothing happening
here is my unittest using Moq
[TestInitialize]
public void Initialize() {
RepositoryMoc= new Mock<ITestRepository>();
_service = new TestService(RepositoryMoc.Object)
}
[TestMethod]
public void UpdateResults_FirstNameRequied() {
User u = new User();
u.FirstName = "";
u.LastName = "Lee";
RepositoryMoc.Setup(r => r.UpdateResults(u));
var result = _service.UpdateResults(u);
Assert.AreEqual("FirstName is required", result.ToString());
}

You've wrote a setup for RepositoryMoc, but it not returning something. If you want that function to return something, write a setup like that:
RepositoryMoc.Setup(r => r.UpdateResults(u)).Returns(<WhateverItHasToReturn>);

Related

how to test fluent validations error message

I am trying to get to grips with TDD, I have reviewed some tutorials and am trying to implement tests on my validation classes that I have created using fluent validation.
public SomeFormValidator()
{
RuleFor(x => x.MyClass).NotNull()
.WithMessage("MyClass cannot be null");
}
I have looked at the TDD examples specifically for fluent validation and created a couple of tests
[Test]
public void Should_have_error_when_MyClass_is_null()
{
MyClass myClass = null;
SomeFormValidator.ShouldHaveValidationErrorFor(aup => aup.MyClass, myClass);
}
[Test]
public void Should_not_have_error_when_MyClass_is_not_null()
{
MyClass myClass = new MyClass();
SomeFormValidator.ShouldNotHaveValidationErrorFor(aup => aup.MyClass, myClass);
}
I would like to now test that the string "MyClass cannot be null" is returned when it is null. I have not been able to find anything covering returned message and I have not been able to work it out.
Thanks to the guidance of #Surgey I was able to come up with a solution that uses the fluent validation built in methods, in addition to that I have been able to better layout my test which I have added below
using FluentValidation.TestHelper;
using NUnit.Framework;
using MyProject.Models...
using MyProject...
namespace MyProject.Tests.Classes.Validation
{
[TestFixture]
public class SomeFormValidatorTest
{
private SomeFormValidator SomeFormValidator;
[SetUp]
public void Setup()
{
SomeFormValidator = new SomeFormValidator();
}
[Test]
public void Should_display_correct_error_message_MyClass_is_null()
{
//arrange
MyClass myClass = null;
//act
var result = SomeFormValidator.ShouldHaveValidationErrorFor(x => x.MyClass, myClass);
//assert
result.WithErrorMessage("MyClass is required");
//first attempt prior to finding WithErrorMessage exists
//foreach (var r in result)
//{
// Assert.AreEqual("MyClass is required", r.ErrorMessage);
//}
}
}
}
I am using result.WithErrorMessage as that is was is provided in the result but I have left the foreach in, but commented, as I find the error message produced by using Assert.AreEqual produce a better message in the test runner.
There is Arrange-Act-Assert (AAA) technique that helps to structure unit tests properly.
Arrange
First of all, you need to create a System Under Test (SUT) and inputs. In this case that are SomeFormValidator and SomeForm instances:
// arrange
var sut = new SomeFormValidator();
var someFormWithNullProp = new SomeForm { MyClass = null };
Act
Then you need to call the SUT to perform real work. For validators, that is the Validate() method call:
// act
ValidationResult result = sut.Validate<SomeForm>(someFormWithNullProp);
Assert
The last part of the unit test checks if the actual result matches the expectations:
// assert
Assert.False(result.IsValid);
Assert.AreEqual(
"MyClass cannot be null",
result.Errors.Single().ErrorMessage);

Instantiate new System.Web.Http.OData.Query.ODataQueryOptions in nunit test of ASP.NET Web API controller

I have an ASP.NET MVC4 Web API project with an ApiController-inheriting controller that accepts an ODataQueryOptions parameter as one of its inputs.
I am using NUnit and Moq to test the project, which allow me to setup canned responses from the relevant repository methods used by the ApiController. This works, as in:
[TestFixture]
public class ProjectControllerTests
{
[Test]
public async Task GetById()
{
var repo = new Mock<IManagementQuery>();
repo.Setup(a => a.GetProjectById(2)).Returns(Task.FromResult<Project>(new Project()
{
ProjectID = 2, ProjectName = "Test project", ProjectClient = 3
}));
var controller = new ProjectController(repo.Object);
var response = await controller.Get(2);
Assert.AreEqual(response.id, 2);
Assert.AreEqual(response.name, "Test project");
Assert.AreEqual(response.clientId, 3);
}
}
The challenge I have is that, to use this pattern, I need to pass in the relevant querystring parameters to the controller as well as the repository (this was actually my intent). However, in the case of ODataQueryOptions-accepting ApiController methods, even in the cases where I would like to use just the default parameters for ODataQueryOptions, I need to know how to instantiate one. This gets tricky:
ODataQueryOptions does not implement an interface, so I can't mock it directly.
The constructor requires an implementation of System.Web.Http.OData.ODataQueryContext, which requires an implementation of something implementing Microsoft.Data.Edm.IEdmModel, for which the documentation is scarce and Visual Studio 2012 Find References and View Call Hierarchy do not provide insight (what implements that interface?).
What do I need to do/Is there a better way of doing this?
Thanks.
Looks like someone else already answered this in the comments here, but it's not a complete solution for my use-case (see comment below):
ODataModelBuilder modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntitySet<Customer>("Customers");
var opts = new ODataQueryOptions<Customer>(new ODataQueryContext(modelBuilder.GetEdmModel(),typeof(Customer)), request);
This is the solution I have been using in my NUnit tests to inject ODataQueryOptions
private static IEdmModel _model;
private static IEdmModel Model
{
get
{
if (_model == null)
{
var builder = new ODataConventionModelBuilder();
var baseType = typeof(MyDbContext);
var sets = baseType.GetProperties().Where(c => c.PropertyType.IsGenericType && c.PropertyType.GetGenericTypeDefinition() == typeof(IDbSet<>));
var entitySetMethod = builder.GetType().GetMethod("EntitySet");
foreach (var set in sets)
{
var genericMethod = entitySetMethod.MakeGenericMethod(set.PropertyType.GetGenericArguments());
genericMethod.Invoke(builder, new object[] { set.Name });
}
_model = builder.GetEdmModel();
}
return _model;
}
}
public static ODataQueryOptions<T> QueryOptions<T>(string query = null)
{
query = query ?? "";
var url = "http://localhost/Test?" + query;
var request = new HttpRequestMessage(HttpMethod.Get, url);
return new ODataQueryOptions<T>(new ODataQueryContext(Model, typeof(T)), request);
}

how to unit test controller when automapper is used?

here's my controller
[POST("signup")]
public virtual ActionResult Signup(UserRegisterViewModel user)
{
if (ModelState.IsValid)
{
var newUser = Mapper.Map<UserRegisterViewModel, User>(user);
var confirmation = _userService.AddUser(newUser);
if (confirmation.WasSuccessful)
return RedirectToAction(MVC.Home.Index());
else
ModelState.AddModelError("Email", confirmation.Message);
}
return View(user);
}
here's my unit test:
[Test]
public void Signup_Action_When_The_User_Model_Is_Valid_Returns_RedirectToRouteResult()
{
// Arrange
const string expectedRouteName = "~/Views/Home/Index.cshtml";
var registeredUser = new UserRegisterViewModel { Email = "newuser#test.com", Password = "123456789".Hash()};
var confirmation = new ActionConfirmation<User>
{
WasSuccessful = true,
Message = "",
Value = new User()
};
_userService.Setup(r => r.AddUser(new User())).Returns(confirmation);
_accountController = new AccountController(_userService.Object);
// Act
var result = _accountController.Signup(registeredUser) as RedirectToRouteResult;
// Assert
Assert.IsNotNull(result, "Should have returned a RedirectToRouteResult");
Assert.AreEqual(expectedRouteName, result.RouteName, "Route name should be {0}", expectedRouteName);
}
Unit test failed right here.
var result = _accountController.Signup(registeredUser) as RedirectToRouteResult;
when I debug my unit test, I got following error message: "Missing type map configuration or unsupported mapping."
I think its because configuration is in web project, not the unit test project. what should I do to fix it?
You need to have the mapper configured, so in your test class set up, not the per-test setup, call the code to set up the mappings. Note, you'll also probably need to modify your expectation for the user service call as the arguments won't match, i.e, they are different objects. Probably you want a test that checks if the properties of the object match those of the model being passed to the method.
You should really use an interface for the mapping engine so that you can mock it rather than using AutoMapper otherwise it is an integration test not a unit test.
AutoMapper has an interface called IMappingEngine that you can inject into your controller using your IoC container like below (this example is using StructureMap).
class MyRegistry : Registry
{
public MyRegistry()
{
For<IMyRepository>().Use<MyRepository>();
For<ILogger>().Use<Logger>();
Mapper.AddProfile(new AutoMapperProfile());
For<IMappingEngine>().Use(() => Mapper.Engine);
}
}
You will then be able to use dependency injection to inject AutoMapper's mapping engine into your controller, allowing you to reference your mappings like below:
[POST("signup")]
public virtual ActionResult Signup(UserRegisterViewModel user)
{
if (ModelState.IsValid)
{
var newUser = this.mappingEngine.Map<UserRegisterViewModel, User>(user);
var confirmation = _userService.AddUser(newUser);
if (confirmation.WasSuccessful)
return RedirectToAction(MVC.Home.Index());
else
ModelState.AddModelError("Email", confirmation.Message);
}
return View(user);
}
You can read more about this here: How to inject AutoMapper IMappingEngine with StructureMap
Probably it is cool to abstract mapping into MappingEngine.
Sometimes I use following approach to IOC Automapper
In IOC builder:
builder.RegisterInstance(AutoMapperConfiguration.GetAutoMapper()).As<IMapper>();
where GetAutoMapper is:
public class AutoMapperConfiguration
{
public static IMapper GetAutoMapper()
{
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile<OrderModelMapperProfile>();
cfg.AddProfile<OtherModelMapperProfile>();
//etc;
});
var mapper = config.CreateMapper();
return mapper;
}
}
And finally in Controller ctor
public MyController(IMapper mapper)
{
_mapper = mapper;
}

Copy a note from a task to a case

I have a manually invoked process which is tied to the account entity. This process has a number of steps. One of the first steps is to create a task and assign it to someone. It's expected that this person will add some notes and complete the task.
Further down the process, I have a step to create a service case. After this is created, I want to copy the note(s) from the task above to the newly created service case.
I have created a custom workflow activity to try and accomplish this. I have gotten as far as deploying it and using it within my process without any errors and it does copy content into the notes field of the service case, however it copies the title of the task, not the note content and I can't quite fathom out why.
public class CopyNotes : CodeActivity
{
protected override void Execute(CodeActivityContext executionContext)
{
//Create the context
IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
//get the notes associated with the source entity
Guid copyFromId = CopyFrom.Get(executionContext).Id;
Guid copyToId = CopyTo.Get(executionContext).Id;
EntityCollection copyFromNotes = RetrieveNotes(service, copyFromId);
if (copyFromNotes.Entities.Any())
{
foreach (Entity e in copyFromNotes.Entities)
{
Entity newNote = new Entity("annotation");
newNote.Attributes["subject"] = e.Attributes["subject"];
newNote.Attributes["notetext"] = e.Attributes["notetext"];
newNote.Attributes["objectid"] = new EntityReference() { Id = copyToId, LogicalName = CopyTo.Get(executionContext).LogicalName };
}
}
}
private EntityCollection RetrieveNotes(IOrganizationService service, Guid relatedObject)
{
ConditionExpression condition = new ConditionExpression();
condition.AttributeName = "objectid";
condition.Operator = ConditionOperator.Equal;
condition.Values.Add(relatedObject.ToString());
ColumnSet columns = new ColumnSet("subject", "notetext");
QueryExpression query = new QueryExpression();
query.ColumnSet = columns;
query.EntityName = "annotation";
query.Criteria.AddCondition(condition);
EntityCollection results = service.RetrieveMultiple(query);
return results;
}
[RequiredArgument]
[ReferenceTarget("task")]
[Input("Copy notes from item")]
public InArgument<EntityReference> CopyFrom { get; set; }
[RequiredArgument]
[ReferenceTarget("incident")]
[Input("Copy notes to item")]
public InArgument<EntityReference> CopyTo { get; set; }
}
I think you need to actually create the newNote after defining it.
foreach (Entity e in copyFromNotes.Entities)
{
Entity newNote = new Entity("annotation");
newNote.Attributes["subject"] = e.Attributes["subject"];
newNote.Attributes["notetext"] = e.Attributes["notetext"];
newNote.Attributes["objectid"] = new EntityReference() { Id = copyToId, LogicalName = CopyTo.Get(executionContext).LogicalName };
service.Create(newNote);
}
Once I did that your code worked just fine creating a new note with both the title and note text.
You could do this with a standard workflow, if Async creation is fast enough.
Andreas

asp.net mvc ObjectDisposedException with ef

I need some help with this error "The ObjectContext instance has been disposed and can no longer be used for operations that require a connection."
It's a asp.net mvc3, EF4, and ms sql.
Here is the razor with two dropdowns:
<div class="editRow">
#Html.DropDownListFor(m=>m.IndustryId, (SelectList)ViewBag.Industry, #Empower.Resource.General.ddlDefaultVal, new { #class = "ddl400" })
#Html.ValidationMessageFor(m => m.IndustryId)
</div>
<div class="editRow">
#Html.DropDownListFor(m=>m.ProvinceId, (SelectList)ViewBag.Province, #Empower.Resource.General.ddlDefaultVal, new {#class = "ddl400"})
#Html.ValidationMessageFor(m => m.ProvinceId)
</div>
Controller:
IndustryService indService = new IndustryService();
ViewBag.Industry = new SelectList(indService.GetAllIndustry(), "IndustryId", "IndustryName");
ProvinceService proService = new ProvinceService();
ViewBag.Province = new SelectList(proService.GetAllProvince(), "ProvinceId", "ProvinceName");
return View();
ProvinceService:
public IEnumerable<Province> GetAllProvince()
{
using (var context = DBContext.ObjectContext)
{
var pros = context.Provinces;
return pros;
}
}
IndustryService is identical as above...
public class DBContext
{
private static EmpowerDBEntities _empowerContext;
public static EmpowerDBEntities ObjectContext
{
get
{
if (_empowerContext == null)
_empowerContext = new EmpowerDBEntities();
return _empowerContext;
}
}
}
I know the problem occurs in second dropdown when it tries to retrive data while the connection is desposed by previous query. Please help me with this, thanks.
The fix is simple - convert to a .ToList() or First() before using. LINQ has deferred execution and tries to run this command after the context is disposed (when your object results are referenced) - not when you actually make the call.. You need to force it to run now while the context is in scope.
using (var context = DBContext.ObjectContext)
{
var pros = context.Provinces;
return pros.ToList();
}
Also - your code above is checking for null in the get accessor. However this object won't be null - it will be disposed, so you cannot do your check this way, you need to check if its null and not disposed.
public class DBContext
{
private static EmpowerDBEntities _empowerContext;
public static EmpowerDBEntities ObjectContext
{
get
{
if (_empowerContext == null || _empowerContext.IsDisposed())
_empowerContext = new EmpowerDBEntities();
return _empowerContext;
}
}
}
something like that anyways :)
I ran into a similar problem. I had been following this pattern, which I had seen in many code examples on the web:
public ActionResult Show(int id)
{
using (var db = new MyDbContext())
{
var thing = db.Things.Find(id);
return View(thing);
}
}
However, this was causing the ObjectDisposedException listed above whenever I tried to access anything that hadn't been loaded into memory in the View code (in particular, one-to-many relationships in the main view model).
I found a different pattern in this example:
public class MyController : Controller
{
private MyDbContext _db;
public MyController()
{
_db = new MyDbContext();
}
public ActionResult Show(int id)
{
// Do work such as...
var thing = _db.Things.Find(id);
return View(thing);
}
protected override void Dispose(bool disposing)
{
_db.Dispose();
base.Dispose(disposing);
}
}
This pattern keeps the database connection alive until the View has finished rendering, and neatly disposes of it when the Controller itself is disposed.
Here is the problem when you are using
using(var context=new CustomerContext())
{
return View(context.Customers.ToList());
}
when the block of code executes all references are disposed that you are lazzy loading so that's why it is throwing this error.
so i used
return View(context.Customers.ToList()) directly it will work perfectly fine.

Resources