I would like to eliminate the loops for better coding and improved performance. So, in below code I need to eliminate loop for test1, test 2, test3.
var test1 = _testP.cdata1(id, sdate)
.Where(t => t.In != null).ToList();
var test2 = _testP.cdata2(id, sdate)
.groupBy(p => p.In.id)
.ToDictionary(p => p.Key, p => p.ToDictionary(q => q.Date, q => q));
var test3 = test1.Select(t =>
{
Dictionary<Date, ClassB> cds = null;
ClassB cd = null;
if (test2.TryGetValue(t.In.Id, out cds)
&& cds.TryGetValue(t.date, out cd))
{
return new Tuple<ClassB, ClassA>(cd, t);
}
return null;
}).Where(p => p != null).ToList();
public IEnumerable<ClassA> cdata1(id, sdate)
{
// do some operations
return listA //(listA is the list of all the elements of ClassA object)
}
public IEnumerable<ClassB> cdata2(id, sdate)
{
// do some operations
return listA //(listA is the list of all the elements of ClassB object)
}
public ClassA
{
public testp in { get; }
public Date date { get; }
// other variables
}
public ClassB
{
public testp in { get; }
public Date date { get; }
// other variables
}
Help me out on writing better code for the above snippet.
Related
I have a Search component that implements a debounce timer so it doesn't call ValueChanged (and therefore doesn't update the property tied to it immediately).
My Issue
The bUnit test doesn't appear to two way bind my value I am updating.
Test code
private string StringProperty { get; set; }
[Fact]
public async Task AfterDebounce_ValueUpdates()
{
var myString = "";
var cut = RenderComponent<Search>(parameters => parameters
.Add(p => p.Value, StringProperty)
.Add(p => p.ValueChanged, (s) => myString = s)
);
var input = cut.Find("input");
input.Input("unit test");
Assert.Equal("unit test", cut.Instance.Value);
Assert.NotEqual("unit test", myString);
//Assert.NotEqual("unit test", StringProperty);
await Task.Delay(5000);
Assert.Equal("unit test", myString);
//Assert.Equal("unit test", StringProperty);
}
I would have expected the commented out parts to work (as they are doing the same thing as the ValueChanged to update the property), but they fail.
The component
public class Search : ComponentBase
{
[Parameter] public string? Value { get; set; }
[Parameter] public EventCallback<string> ValueChanged { get; set; }
[DisallowNull] public ElementReference? Element { get; protected set; }
private System.Timers.Timer timer = null;
protected string? CurrentValue {
get => Value;
set {
var hasChanged = !EqualityComparer<string>.Default.Equals(value, Value);
if (hasChanged)
{
Value = value;
DisposeTimer();
timer = new System.Timers.Timer(350);
timer.Elapsed += TimerElapsed_TickAsync;
timer.Enabled = true;
timer.Start();
}
}
}
private void DisposeTimer()
{
if (timer != null)
{
timer.Enabled = false;
timer.Elapsed -= TimerElapsed_TickAsync;
timer.Dispose();
timer = null;
}
}
private async void TimerElapsed_TickAsync(
object sender,
EventArgs e)
{
await ValueChanged.InvokeAsync(Value);
}
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.OpenElement(10, "input");
builder.AddAttribute(20, "type", "text");
builder.AddAttribute(60, "value", BindConverter.FormatValue(CurrentValue));
builder.AddAttribute(70, "oninput", EventCallback.Factory.CreateBinder<string?>(this, __value => CurrentValue = __value, CurrentValue));
builder.AddElementReferenceCapture(80, __inputReference => Element = __inputReference);
builder.CloseElement();
}
}
How it is used:
It may be used like this where the grid will update whenever Query is updated.
<Search #bind-Value=Query />
<Grid Query=#Query />
#code {
private string? Query { get; set; }
}
This works fine in practice, but when testing I am having issues.
I tried locally on my machine, and the test passed.
Here is a simplified version of your component, that only calls TimerElapsed_TickAsync one time per value change and not every time the timer runs out (AutoReset defaults to true), and two different ways to write the test that both pass on my machine:
public class Search : ComponentBase, IDisposable
{
private readonly Timer timer;
[Parameter] public string? Value { get; set; }
[Parameter] public EventCallback<string> ValueChanged { get; set; }
[DisallowNull] public ElementReference? Element { get; protected set; }
public Search()
{
timer = new Timer(350);
timer.Elapsed += TimerElapsed_TickAsync;
timer.Enabled = true;
timer.AutoReset = false;
}
protected string? CurrentValue
{
get => Value;
set
{
var hasChanged = !EqualityComparer<string>.Default.Equals(value, Value);
if (hasChanged)
{
RestartTimer();
Value = value;
}
}
}
private void RestartTimer()
{
if (timer.Enabled)
timer.Stop();
timer.Start();
}
private void TimerElapsed_TickAsync(object sender, EventArgs e)
=> ValueChanged.InvokeAsync(Value);
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.OpenElement(10, "input");
builder.AddAttribute(20, "type", "text");
builder.AddAttribute(60, "value", BindConverter.FormatValue(CurrentValue));
builder.AddAttribute(70, "oninput", EventCallback.Factory.CreateBinder<string?>(this, __value => CurrentValue = __value, CurrentValue));
builder.AddElementReferenceCapture(80, __inputReference => Element = __inputReference);
builder.CloseElement();
}
public void Dispose() => timer.Dispose();
}
And the C# version of the test:
[Fact]
public async Task AfterDebounce_ValueUpdates()
{
var expected = "test input";
var count = 0;
var value = "";
var cut = RenderComponent<Search>(parameters => parameters
.Add(p => p.Value, value)
.Add(p => p.ValueChanged, (s) =>
{
value = s;
count++;
})
);
cut.Find("input").Input(expected);
await Task.Delay(350);
Assert.Equal(1, count);
Assert.Equal(expected, value);
}
and the .razor version of the test (aka. written in a .razor file):
#inherits TestContext
#code
{
[Fact]
public async Task AfterDebounce_ValueUpdates()
{
var expected = "test input";
var value = "";
var cut = Render(#<Search #bind-Value="value" /> );
cut.Find("input").Input(expected);
await Task.Delay(350);
Assert.Equal(expected, value);
}
}
I have an Interface to check vowel and to return a char as
public interface IVowChecker
{
bool VowCheck(char a);
char ReturnChar(int n);
Student GetStudentById(int n);
}
It's concrete class implementation
public class VowChecker:IVowChecker
{
public bool VowCheck(char a)
{
if (a == 'a' || a == 'A')
return true;
return false;
}
public char ReturnChar(int n)
{
return (char)n;
}
public Student GetStudentById(int n)
{
var list = new []
{
new Student{RollNo=1,Name="A"},
new Student{RollNo=2,Name="B"},
new Student{RollNo=3,Name="C"},
new Student{RollNo=4,Name="D"},
new Student{RollNo=5,Name="E"},
new Student{RollNo=6,Name="F"},
};
var student = from i in list
where i.RollNo == n
select i;
return student.FirstOrDefault();
}
}
And a service using this VowChecker
public class MyCharService
{
private readonly IVowChecker _checker;
public MyCharService(IVowChecker checker)
{
_checker = checker;
}
public bool CheckInput(char a)
{
return _checker.VowCheck(a);
}
public char ReturnChar(int a)
{
return _checker.ReturnChar(a);
}
public Student GetStudentById(int n)
{
return _checker.GetStudentById(n);
}
}
I am using Xunit testing framework for unit testing and Moq library.
My unit test code is
public class MyCharServiceShould
{
...
[Theory]
[InlineData(65)]
[InlineData(68)]
public void BeAbleToReturnChar(int n)
{
var service = new Mock<IVowChecker>();
service.Setup(i => i.ReturnChar(n)).Returns('A');
var obj = new MyCharService(service.Object);
var result = obj.ReturnChar(n);
}
[Theory]
[InlineData(2)]
public void BeAbleToRetrieveStudent(int n)
{
var service = new Mock<IVowChecker>();
service.Setup<Student>(i => i.GetStudentById(n)).Returns<Student>(f => (Student)f);
var ob = new MyCharService(service.Object);
var res = ob.GetStudentById(2);
Assert.Equal(res.Name, "B");
}
}
My Student class
public class Student
{
public int RollNo{ get; set; }
public string Name { get; set; }
}
I have used a debugger in the last line of my test and checked the values of both the tests. For the 1st test I am expecting 'A' as the result and for the 2nd test I am expecting 'D' as the result. But in both the cases I am getting 'A' as the result. Can anyone kindly help me out where I am missing out the concept. Thank you.
The problem is that the setup for ReturnChar
service.Setup(i => i.ReturnChar(n)).Returns('A');
says,
Whenever ReturnChar() is called, give an answer of 'A'
It ignores the input 'n' and just returns 'A'. If you want it to return a different character for each test you will need to tweak the setup.
Perhaps
mockService.Setup(mk => mk.ReturnChar(It.IsAny<int>())).Returns<int>(n => (char)n);
EDIT: Extension to show returning objects (and fixed syntax on previous answer)
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
}
public interface IService
{
Student FindStudentById(int id);
}
[TestMethod]
public void FindStudents()
{
var students = new[]
{
new Student {Id = 1, Name = "Mon" },
new Student {Id = 2, Name = "Tue" },
new Student {Id = 3, Name = "Wed" },
new Student {Id = 4, Name = "Thu" },
};
var mockService = new Mock<IService>();
mockService.Setup(mk => mk.FindStudentById(It.IsAny<int>())).Returns<int>(id => students.First(s => s.Id == id));
Assert.AreEqual("Wed", mockService.Object.FindStudentById(3).Name);
}
I'm new to nUnit and I've been tasked with creating unit tests for some htmlhelper extension methods.
How should I go about creating a unit test for the following method?
public static MvcHtmlString EnumDropDownListForOrderBy<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, bool orderById, string firstElement = null, object htmlAttributes = null)
{
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
Type enumType = GetNonNullableModelType(metadata);
IEnumerable<TEnum> values = Enum.GetValues(enumType).Cast<TEnum>();
IEnumerable<SelectListItem> items = values.Select(value => new SelectListItem()
{
Text = value.GetAttributeFrom<DescriptionAttribute>(value.ToString()).Description,
Value = value.ToString(),
Selected = value.Equals(metadata.Model)
});
IEnumerable<SelectListItem> itemsFiltered = items.Where(e => !string.IsNullOrEmpty(e.Text)).AsEnumerable();
itemsFiltered = itemsFiltered.OrderBy(e => (orderById ? e.Text : e.Value));
return htmlHelper.DropDownListFor(
expression,
itemsFiltered,
firstElement,
htmlAttributes
);
}
Any help would be appreciated
Below is how you write a Unit Test for this. Note that since you have not specified that you use a Mock object framework I'm going to the poor man technique, which is the hand written stubs and mocks. There is also another helper method if you are using Moq.
It is important to note that, in order to simplify the code execution I have made couple of changes to your extension method, so the test would not fail unexpectedly. Checking for any unexpected behaver is a good defensive programming practice anyway.
Back to the tests.
SUT (System Under Test)
This is how the SUT (System Under Test) looks like and supporting types looks like. (Please feel free to modify to your need accordingly)
public static class MyHtmlHelper
{
public static MvcHtmlString EnumDropDownListForOrderBy<TModel, TEnum>
(this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TEnum>> expression,
bool orderById, string firstElement = null, object htmlAttributes = null,
Func<ModelMetadata> fromLambFunc = null)
{
ModelMetadata metadata =
ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
Type enumType = GetNonNullableModelType(metadata);
IEnumerable<TEnum> values = Enum.GetValues(enumType).Cast<TEnum>();
IEnumerable<SelectListItem> items =
values.Select(value => new SelectListItem()
{
Text = GetText(value),
Value = value.ToString(),
Selected = value.Equals(metadata.Model)
});
IEnumerable<SelectListItem> itemsFiltered =
items.Where(e => !string.IsNullOrEmpty(e.Text)).AsEnumerable();
itemsFiltered = itemsFiltered.OrderBy(e => (orderById ? e.Text : e.Value));
return htmlHelper.DropDownListFor
(expression, itemsFiltered, firstElement, htmlAttributes);
}
private static Type GetNonNullableModelType(ModelMetadata metadata) {
return typeof (SomeEnum);
}
private static string GetText<TEnum>(TEnum value) {
return value.GetAttributeFrom<DescriptionAttribute>(value.ToString()) != null
? value.GetAttributeFrom<DescriptionAttribute>(value.ToString()).Description
: string.Empty;
}
}
public static class ExtensionMethodsAttr
{
public static T GetAttributeFrom<T>(this object instance, string propertyName)
where T : Attribute
{
var attrType = typeof(T);
var property = instance.GetType().GetProperty(propertyName);
return property != null ?
(T)property.GetCustomAttributes(attrType, false).First() : default(T) ;
}
}
public enum SomeEnum { A,}
Unit Tests
[TestFixture]
public class HtmlHelperTests
{
[Test]
public void EnumDropDownListForOrderBy_InvokeDropDownListFor_ReturnsExpectedSelectItemResult()
{
//Arrange
var expected = "<select id=\"Foo\" name=\"Foo\"></select>";
var fakeHtmlHelper = CreateHtmlHelperStaticStubs
(new ViewDataDictionary(new FakeViewModel() {Foo = SomeEnum.A}));
//var fakeHtmlHelper = CreateHtmlHelperUsingMoq
(new ViewDataDictionary(new FakeViewModel(){Foo = SomeEnum.A}));
//Act
var result = fakeHtmlHelper.EnumDropDownListForOrderBy
(model => model.Foo, It.IsAny<bool>(), null, null, null);
//Assert
Assert.AreEqual(expected, result.ToString());
}
private static HtmlHelper<FakeViewModel>
CreateHtmlHelperStaticStubs(ViewDataDictionary viewData)
{
var stubControllerContext = new ControllerContext(new FakeHttpContext(), new RouteData(), new FakeController());
var stubViewContext = new ViewContext(stubControllerContext, new FakeView(),
new ViewDataDictionary(new FakeViewModel() { Foo = SomeEnum.A }),
new TempDataDictionary(), new TextMessageWriter());
var fakeViewDataContainer = new FakeViewDataContainer();
fakeViewDataContainer.ViewData = viewData;
return new HtmlHelper<FakeViewModel>(stubViewContext, fakeViewDataContainer);
}
//Moq version
private static HtmlHelper<FakeViewModel>
CreateHtmlHelperUsingMoq(ViewDataDictionary viewData)
{
var stubControllerContext = new Mock<ControllerContext>();
stubControllerContext.Setup(x => x.HttpContext).Returns(new Mock<HttpContextBase>().Object);
stubControllerContext.Setup(x => x.RouteData).Returns(new RouteData());
stubControllerContext.Setup(x => x.Controller).Returns(new Mock<ControllerBase>().Object); ;
var stubViewContext = new Mock<ViewContext>();
stubViewContext.Setup(x => x.View).Returns(new Mock<IView>().Object);
stubViewContext.Setup(x => x.ViewData).Returns(viewData);
stubViewContext.Setup(x => x.TempData).Returns(new TempDataDictionary());
var mockViewDataContainer = new Mock<IViewDataContainer>();
mockViewDataContainer.Setup(v => v.ViewData).Returns(viewData);
return new HtmlHelper<FakeViewModel>(stubViewContext.Object, mockViewDataContainer.Object);
}
}
class FakeHttpContext : HttpContextBase
{
private Dictionary<object, object> _items = new Dictionary<object, object>();
public override IDictionary Items { get { return _items; } }
}
class FakeViewDataContainer : IViewDataContainer
{
private ViewDataDictionary _viewData = new ViewDataDictionary();
public ViewDataDictionary ViewData { get { return _viewData; } set { _viewData = value; } }
}
class FakeController : Controller { }
class FakeView : IView
{
public void Render(ViewContext viewContext, System.IO.TextWriter writer)
{
throw new NotImplementedException();
}
}
public class FakeViewModel {
public SomeEnum Foo { get; set; }
}
I'm trying to use the Onion Pattern with Generic Repositories + Unit of work + Entity Framework 5 + Ninject with Asp.net MVC4 but I'm having a problem with EF "DetectChanges" feature and I don't understand why I need to set it to "false".
Could you please help me?
My solution is to add the following line to the constructor of FindingBugContext.cs file:
Configuration.AutoDetectChangesEnabled = false;
In the commented lines of the following code, I'll explain more clearly my isssue.
It's a very simple (and maybe stupid) code reproducing the issue I don't understand and I didn't include the code for all interfaces because I think it's pretty simple to figure it out.
This is my service class, "RobotService.cs":
public class RobotService : IRobotService
{
private readonly IRepository<Body> _repoBody;
private readonly IRepository<BodyPart> _repoBodyPart;
private readonly IRepository<Robot> _repoRobot;
private readonly IUnitOfWork _unitOfWork;
public RobotService(
IRepository<Body> repoBody,
IRepository<BodyPart> repoBodyPart,
IRepository<Robot> repoRobot,
IUnitOfWork unitOfWork)
{
_repoBody = repoBody;
_repoBodyPart = repoBodyPart;
_repoRobot = repoRobot;
_unitOfWork = unitOfWork;
}
public Robot Get(int id)
{
Robot robot = new Robot();
robot = _repoRobot.Get(id);
if (robot != null)
{
Body body = _repoBody.Get(robot.BodyId);
/* FROM NOW ON:
* robot.BodyId = 0 --> instead of 1: WHY???
* robot.Name = "Robby1"
*/
if (body != null)
{
BodyPart head = new BodyPart();
head = _repoBodyPart.Get(body.HeadId);
body.Head = head;
/* FROM NOW ON:
* body.BodyId = 0 --> instead of 1: WHY???
* body.HeadId = 0 --> instead of 1: WHY???
* body.LeftArmId = 0 --> instead of 2: WHY???
* body.RightArmId = 0 --> instead of 3: WHY???
* body.BodyName = "Body1" --> doesn't change
*/
BodyPart leftArm = new BodyPart();
leftArm = _repoBodyPart.Get(body.LeftArmId);
body.LeftArm = leftArm;
BodyPart rightArm = new BodyPart();
rightArm = _repoBodyPart.Get(body.RightArmId);
body.RightArm = rightArm;
robot.Body = body;
}
}
return robot;
}
This is my custom code inside NinjectWebCommon.cs file after installation through NuGet package "Ninject.MVC3":
private static void RegisterServices(IKernel kernel)
{
kernel.Bind(typeof(IRepository<>)).To(typeof(RepositoryBase<>)).InRequestScope();
kernel.Bind<IDbContextFactory>().To<DbContextFactory>().InRequestScope();
kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
kernel.Bind<IRobotService>().To<RobotService>();
}
This is my DbContext class "FindingBugContext.cs":
public class FindingBugContext : DbContext
{
public FindingBugContext()
: base("FindingBugContext")
{
//Configuration.AutoDetectChangesEnabled = false; //This is the solution
}
public virtual void Commit()
{
base.SaveChanges();
}
private IDbSet<Robot> _robots;
private IDbSet<Body> _bodies;
private IDbSet<BodyPart> _bodyParts;
public virtual IDbSet<T> DbSet<T>() where T : class
{
return Set<T>();
}
public IDbSet<Robot> Robots
{
get { return _robots ?? (_robots = DbSet<Robot>()); }
}
public IDbSet<Body> Bodies
{
get { return _bodies ?? (_bodies = DbSet<Body>()); }
}
public IDbSet<BodyPart> BodyParts
{
get { return _bodyParts ?? (_bodyParts = DbSet<BodyPart>()); }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer(new DropCreateFindingBugWithSeedData());
modelBuilder.Configurations.Add(new RobotConfiguration());
modelBuilder.Configurations.Add(new BodyConfiguration());
modelBuilder.Configurations.Add(new BodyPartConfiguration());
}
public class DropCreateFindingBugWithSeedData : DropCreateDatabaseAlways<FindingBugContext>
{
protected override void Seed(FindingBugContext context)
{
BodyPart head = new BodyPart() { Type = PartType.Head, PartName = "Head" };
BodyPart leftArm = new BodyPart() { Type = PartType.LeftArm, PartName = "LeftArm" };
BodyPart rightArm = new BodyPart() { Type = PartType.RightArm, PartName = "RightArm" };
Body body = new Body() { BodyName = "Body1", Head = head, HeadId = 1, LeftArm = leftArm, LeftArmId = 2, RightArm = rightArm, RightArmId = 3 };
Robot robot = new Robot() { Name = "Robby1", BodyId = 1, Body = body };
context.Robots.Add(robot);
}
}
public class RobotConfiguration : EntityTypeConfiguration<Robot>
{
public RobotConfiguration()
{
ToTable("Robots");
HasKey(r => r.RobotId)
.Property(r => r.RobotId)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
HasRequired(r => r.Body)
.WithMany()
.HasForeignKey(r => r.BodyId);
}
}
public class BodyConfiguration : EntityTypeConfiguration<Body>
{
public BodyConfiguration()
{
ToTable("Bodies");
HasKey(b => b.BodyId)
.Property(b => b.BodyId)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
HasRequired(b => b.Head)
.WithMany()
.HasForeignKey(b => b.HeadId)
.WillCascadeOnDelete(false);
HasRequired(b => b.LeftArm)
.WithMany()
.HasForeignKey(b => b.LeftArmId)
.WillCascadeOnDelete(false);
HasRequired(b => b.RightArm)
.WithMany()
.HasForeignKey(b => b.RightArmId)
.WillCascadeOnDelete(false);
}
}
public class BodyPartConfiguration : EntityTypeConfiguration<BodyPart>
{
public BodyPartConfiguration()
{
ToTable("BodyParts");
HasKey(b => b.BodyPartId)
.Property(b => b.BodyPartId)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
}
}
}
These are my Entities:
public class Robot
{
public Robot() { Body = new Body(); }
public int RobotId { get; set; }
public string Name { get; set; }
public int BodyId { get; set; }
public Body Body { get; set; }
}
public class Body
{
public Body()
{
Head = new BodyPart();
LeftArm = new BodyPart();
RightArm = new BodyPart();
}
public int BodyId { get; set; }
public string BodyName { get; set; }
public int HeadId { get; set; }
public BodyPart Head { get; set; }
public int LeftArmId { get; set; }
public BodyPart LeftArm { get; set; }
public int RightArmId { get; set; }
public BodyPart RightArm { get; set; }
}
public class BodyPart
{
public int BodyPartId { get; set; }
public PartType Type { get; set; }
public string PartName { get; set; }
}
public enum PartType
{
Head,
LeftArm,
RightArm
}
This is the Unit of Work code:
public class UnitOfWork : IUnitOfWork
{
private readonly IDbContextFactory _dbContextFactory;
private FindingBugContext _context;
public UnitOfWork(IDbContextFactory dbContextFactory)
{
_dbContextFactory = dbContextFactory;
}
protected FindingBugContext FindingBugContext
{
get { return _context ?? (_context = _dbContextFactory.Get()); }
}
public void Commit()
{
FindingBugContext.Commit();
}
}
This is the Generic Repository code:
public class RepositoryBase<T> : IRepository<T> where T : class
{
private FindingBugContext _context;
private readonly IDbSet<T> _dbSet;
public RepositoryBase(IDbContextFactory dbContextFactory)
{
DbContextFactory = dbContextFactory;
_dbSet = FindingBugContext.Set<T>();
}
public IDbContextFactory DbContextFactory
{
get;
private set;
}
public FindingBugContext FindingBugContext
{
get { return _context ?? (_context = DbContextFactory.Get()); }
}
//Read
public T Get(int id)
{
return _dbSet.Find(id);
}
}
This is my ContextFactory code:
public class DbContextFactory : Disposable, IDbContextFactory
{
private FindingBugContext _context;
public FindingBugContext Get()
{
if (_context == null)
{
_context = new FindingBugContext();
return _context;
}
else
{
return _context;
}
}
public void Dispose()
{
if (_context != null)
{
_context.Dispose();
}
}
}
I am using Rhino mock for mocking in my test methods. Could someone please see the TODO part in the test method and help me to mock it?
This is my service interface:
public interface ICustomersServiceAgent
{
void GetCustomers(EventHandler<GetCustomersCompletedEventArgs> callback);
void SaveCustomer(POC.Model.Customer cust, EventHandler<SaveCustomerCompletedEventArgs> callback);
}
This is my ViewModel
public class CustomerVM : ViewModelBase
{
private Model.Customer _curentCustomer;
private RelayCommand _saveCommand;
private ICustomersServiceAgent ServiceAgent { get; set; }
private bool isSaved;
private RelayCommand _calculateAgeCommand;
private Decimal age;
private DateTime dateOfBirth;
public CustomerVM(ICustomersServiceAgent serviceAgent)
{
if (serviceAgent == null)
{
ServiceAgent = ServiceManager.GetCustomerServiceManagement();
}
else
{
ServiceAgent =serviceAgent;
}
WireCommands();
}
// if curent object is null then it should be intialize
public Model.Customer CurentCustomer
{
get { return _curentCustomer ?? (_curentCustomer = new Model.Customer()); }
set
{
if (_curentCustomer != value)
{
_curentCustomer = value;
OnPropertyChanged("CurentCustomer");
}
}
}
public RelayCommand CalculateAgeCommand
{
get;
private set;
}
private void WireCommands()
{
SaveCustomerCommand = new RelayCommand(SaveCustomer);
SaveCustomerCommand.IsEnabled = true;
CalculateAgeCommand = new RelayCommand(CalculateAge);
}
private void SaveCustomer()
{
var cus = CurentCustomer;
ServiceAgent.SaveCustomer(cus, (s, e) =>
{
IsSaved = e.Result;
});
}
private void CalculateAge()
{
Age = DateTime.Now.Year - DateOfBirth.Year;
}
public RelayCommand SaveCustomerCommand
{
get;
private set;
}
public bool IsSaved
{
get { return isSaved; }
set
{
isSaved = value;
OnPropertyChanged("IsSaved");
}
}
public decimal Age
{
get { return age; }
set {
age = value;
OnPropertyChanged("Age");
}
}
public DateTime DateOfBirth
{
get { return dateOfBirth; }
set {
dateOfBirth = value;
OnPropertyChanged("DateOfBirth");
}
}
}
I want to test the SaveCustomerCommand in ViewModel above.
So In the my test method, I want to mock the void SaveCustomer(POC.Model.Customer cust, EventHandler<SaveCustomerCompletedEventArgs> callback) method in the ICustomersServiceAgent interface.
This is my test method, see the ToDo part
[TestMethod]
public void SaveCustomerCommandTest()
{
var customerServiceMock = MockRepository.GenerateMock<ICustomersServiceAgent>();
var customerVM = new POC.SilverlightClient.ViewModel.CustomerVM(customerServiceMock);
// TO do : Code to mock SaveCustomer method ///////////////////////////////////
var saveCustomerCommand = customerVM.SaveCustomerCommand;
saveCustomerCommand.Execute(null);
Assert.IsTrue(customerVM.IsSaved);
}
Could someone please explain how I can do this?
I don't see why you need to mock SaveCustomer. All the private SaveCustomer method does is invoke the ServiceAgent service which you already are mocking. I assume the RelayCommand class invokes the delegate you're sending in the constructor parameter which is the call to SaveCustomer. Have you tried running the unit test in your question as-is?
Try following:
customerServiceMock.Stub(sa => sa.SaveCustomer(Arg<POC.Model.Customer>.Is.Anything, Arg<EventHandler<SaveCustomerCompletedEventArgs>>.Is.Anything)).WhenCalled(invocation =>
{
((EventHandler<SaveCustomerCompletedEventArgs>)invocation.Arguments[1])(
customerServiceMock,
new SaveCustomerCompletedEventArgs { Result = true });
});